diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-06-27 07:34:52 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-06-27 07:34:52 +0000 |
commit | ce784e5c99ddddb454ab402d7ed423c9eee03d3b (patch) | |
tree | 39de08ecd2e441cf33cdb795807fa3ab4fb2d0d5 | |
parent | 202ff857c7b27103756737b433f9bdcb1b805ed1 (diff) | |
download | gnutls-ce784e5c99ddddb454ab402d7ed423c9eee03d3b.tar.gz |
Added ability to write Bag attributes LocalKeyId and friendlyName, in order for browsers to be able to import our structures.
-rw-r--r-- | lib/pkix.asn | 6 | ||||
-rw-r--r-- | lib/pkix_asn1_tab.c | 8 | ||||
-rw-r--r-- | lib/x509/common.c | 3 | ||||
-rw-r--r-- | lib/x509/dn.c | 29 | ||||
-rw-r--r-- | lib/x509/pkcs12.c | 125 | ||||
-rw-r--r-- | lib/x509/pkcs12.h | 10 | ||||
-rw-r--r-- | lib/x509/pkcs12_bag.c | 178 |
7 files changed, 294 insertions, 65 deletions
diff --git a/lib/pkix.asn b/lib/pkix.asn index 8933e7ae2d..aa9ac0ec1e 100644 --- a/lib/pkix.asn +++ b/lib/pkix.asn @@ -1028,8 +1028,14 @@ pkcs-9-challengePassword ::= CHOICE { printableString PrintableString (SIZE (1..pkcs-9-ub-challengePassword)), utf8String UTF8String (SIZE (1..pkcs-9-ub-challengePassword)) } +pkcs-9-at-localKeyId OBJECT IDENTIFIER ::= {pkcs-9 21} + pkcs-9-localKeyId ::= OCTET STRING +pkcs-9-at-friendlyName OBJECT IDENTIFIER ::= {pkcs-9 20} + +pkcs-9-friendlyName ::= BMPString (SIZE (1..255)) + -- PKCS #8 stuff -- Private-key information syntax diff --git a/lib/pkix_asn1_tab.c b/lib/pkix_asn1_tab.c index e5d9bbbd6c..9922313d05 100644 --- a/lib/pkix_asn1_tab.c +++ b/lib/pkix_asn1_tab.c @@ -928,7 +928,15 @@ const ASN1_ARRAY_TYPE pkix_asn1_tab[]={ {"pkcs-9-ub-challengePassword",524298,"1"}, {"utf8String",538968066,"UTF8String"}, {"pkcs-9-ub-challengePassword",524298,"1"}, + {"pkcs-9-at-localKeyId",1879048204,0}, + {0,1073741825,"pkcs-9"}, + {0,1,"21"}, {"pkcs-9-localKeyId",1073741831,0}, + {"pkcs-9-at-friendlyName",1879048204,0}, + {0,1073741825,"pkcs-9"}, + {0,1,"20"}, + {"pkcs-9-friendlyName",1612709890,"BMPString"}, + {"255",524298,"1"}, {"pkcs-8-PrivateKeyInfo",1610612741,0}, {"version",1073741826,"pkcs-8-Version"}, {"privateKeyAlgorithm",1073741826,"AlgorithmIdentifier"}, diff --git a/lib/x509/common.c b/lib/x509/common.c index c65d4518de..60d7487d20 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -55,6 +55,9 @@ static const oid2string _oid2str[] = { {"0.9.2342.19200300.100.1.1", "UID", 0, 1}, /* FIXME: CHOICE? */ {"1.2.840.113549.1.9.1", "EMAIL", 0, 1}, {"1.2.840.113549.1.9.7", NULL, 1, 1}, + + /* friendly name */ + {"1.2.840.113549.1.9.20", NULL, 0, 1}, {NULL, NULL, 0, 0} }; diff --git a/lib/x509/dn.c b/lib/x509/dn.c index c962ad33a9..fcf565f271 100644 --- a/lib/x509/dn.c +++ b/lib/x509/dn.c @@ -491,8 +491,7 @@ int _gnutls_x509_encode_and_write_attribute( const char* given_oid, ASN1_TYPE as const char *val_name; char tmp[128]; ASN1_TYPE c2; -opaque *der; -int der_len, result; +int result; /* Find how to encode the data. @@ -502,6 +501,7 @@ int der_len, result; gnutls_assert(); return GNUTLS_E_ASN1_GENERIC_ERROR; } +fprintf(stderr, "%s %s\n", given_oid, val_name); _gnutls_str_cpy( tmp, sizeof(tmp), "PKIX1."); _gnutls_str_cat( tmp, sizeof(tmp), val_name); @@ -514,7 +514,7 @@ int der_len, result; tmp[0] = 0; - if (_gnutls_x509_oid_data_choice( given_oid) == 1) { + if ((result=_gnutls_x509_oid_data_choice( given_oid)) > 0) { char* string_type; int i; @@ -550,19 +550,6 @@ int der_len, result; return _gnutls_asn2err(result); } - der_len = 0; - asn1_der_coding( c2, "", NULL, &der_len, NULL); - - der = gnutls_alloca( der_len); - result = asn1_der_coding( c2, "", der, &der_len, NULL); - - asn1_delete_structure( &c2); - - if (result != ASN1_SUCCESS) { - gnutls_assert(); - gnutls_afree(der); - return _gnutls_asn2err(result); - } /* write the data (value) */ @@ -576,7 +563,6 @@ int der_len, result; result = asn1_write_value( asn1_struct, tmp, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert(); - gnutls_afree(der); return _gnutls_asn2err(result); } @@ -584,13 +570,10 @@ int der_len, result; } - result = asn1_write_value( asn1_struct, tmp, der, der_len); - - gnutls_afree(der); - - if (result != ASN1_SUCCESS) { + result = _gnutls_x509_der_encode_and_copy( c2, "", asn1_struct, tmp, 0); + if (result < 0) { gnutls_assert(); - return _gnutls_asn2err(result); + return result; } /* write the type diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c index fcee84af83..309eefec89 100644 --- a/lib/x509/pkcs12.c +++ b/lib/x509/pkcs12.c @@ -336,7 +336,7 @@ char counter[MAX_INT_DIGITS]; _gnutls_str_cat( root, sizeof(root), counter); _gnutls_str_cat( root, sizeof(root), ".bagValue"); - result = _gnutls_x509_read_value( c2, root, &bag->data[i], 0); + result = _gnutls_x509_read_value( c2, root, &bag->element[i].data, 0); if (result < 0) { gnutls_assert(); goto cleanup; @@ -344,9 +344,9 @@ char counter[MAX_INT_DIGITS]; if (bag_type == GNUTLS_BAG_CERTIFICATE || bag_type == GNUTLS_BAG_CRL) { - gnutls_datum tmp = bag->data[i]; + gnutls_datum tmp = bag->element[i].data; - result = _pkcs12_decode_crt_bag( bag_type, &tmp, &bag->data[i]); + result = _pkcs12_decode_crt_bag( bag_type, &tmp, &bag->element[i].data); if (result < 0) { gnutls_assert(); goto cleanup; @@ -355,7 +355,7 @@ char counter[MAX_INT_DIGITS]; _gnutls_free_datum( &tmp); } - bag->type[i] = bag_type; + bag->element[i].type = bag_type; } @@ -471,10 +471,10 @@ int gnutls_pkcs12_get_bag(gnutls_pkcs12 pkcs12, /* ENC_DATA_OID needs decryption */ - bag->type[0] = GNUTLS_BAG_ENCRYPTED; + bag->element[0].type = GNUTLS_BAG_ENCRYPTED; bag->bag_elements = 1; - result = _gnutls_x509_read_value( c2, root2, &bag->data[0], 0); + result = _gnutls_x509_read_value( c2, root2, &bag->element[0].data, 0); if (result < 0) { gnutls_assert(); return result; @@ -609,7 +609,7 @@ int gnutls_pkcs12_set_bag(gnutls_pkcs12 pkcs12, gnutls_pkcs12_bag bag) if (enc) { /* Encrypted packets are written directly. */ - result = asn1_write_value( c2, "?LAST.content", bag->data[0].data, bag->data[0].size); + result = asn1_write_value( c2, "?LAST.content", bag->element[0].data.data, bag->element[0].data.size); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); @@ -747,6 +747,99 @@ int gnutls_pkcs12_generate_mac(gnutls_pkcs12 pkcs12, const char* pass) return result; } +#define FRIENDLY_NAME_OID "1.2.840.113549.1.9.20" +#define KEY_ID_OID "1.2.840.113549.1.9.21" + +static int write_attributes( gnutls_pkcs12_bag bag, int elem, ASN1_TYPE c2, const char* where) { +int result; +char root[128]; + + /* If the bag attributes are empty, then write + * nothing to the attribute field. + */ + if (bag->element[elem].friendly_name == NULL && + bag->element[elem].local_key_id.data == NULL) { + /* no attributes + */ + result = asn1_write_value(c2, where, NULL, 0); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + return 0; + } + + if (bag->element[elem].local_key_id.data != NULL) { + + /* Add a new Attribute + */ + result = asn1_write_value(c2, where, "NEW", 1); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + _gnutls_str_cpy( root, sizeof(root), where); + _gnutls_str_cat( root, sizeof(root), ".?LAST"); + + result = _gnutls_x509_encode_and_write_attribute( + KEY_ID_OID, c2, root, bag->element[elem].local_key_id.data, + bag->element[elem].local_key_id.size, 1); + if (result < 0) { + gnutls_assert(); + return result; + } + } + + if (bag->element[elem].friendly_name != NULL) { + opaque* name; + int size, i; + const char* p; + + /* Add a new Attribute + */ + result = asn1_write_value(c2, where, "NEW", 1); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + /* convert name to BMPString + */ + size = strlen(bag->element[elem].friendly_name)*2; + name = gnutls_malloc(size); + + if (name == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + p = bag->element[elem].friendly_name; + for (i=0;i<size;i+=2) { + name[i] = 0; + name[i+1] = *p; + p++; + } + + _gnutls_str_cpy( root, sizeof(root), where); + _gnutls_str_cat( root, sizeof(root), ".?LAST"); + + result = _gnutls_x509_encode_and_write_attribute( + FRIENDLY_NAME_OID, c2, root, name, size, 1); + + gnutls_free(name); + + if (result < 0) { + gnutls_assert(); + return result; + } + } + + return 0; +} + + /* Encodes the bag into a SafeContents structure, and puts the output in * the given datum. Enc is set to non zero if the data are encrypted; */ @@ -758,7 +851,7 @@ int result; int i; const char* oid; - if (bag->type[0] == GNUTLS_BAG_ENCRYPTED && enc) { + if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc) { *enc = 1; return 0; /* ENCRYPTED BAG, do nothing. */ } else if (enc) *enc = 0; @@ -775,7 +868,7 @@ const char* oid; for (i=0;i<bag->bag_elements;i++) { - oid = bag2oid( bag->type[i]); + oid = bag2oid( bag->element[i].type); if (oid==NULL) { gnutls_assert(); continue; @@ -799,25 +892,25 @@ const char* oid; /* Set empty attributes */ - result = asn1_write_value(c2, "?LAST.bagAttributes", NULL, 0); - if (result != ASN1_SUCCESS) { + result = write_attributes(bag, i, c2, "?LAST.bagAttributes"); + if (result < 0) { gnutls_assert(); - result = _gnutls_asn2err(result); goto cleanup; } + /* Copy the Bag Value */ - if (bag->type[i] == GNUTLS_BAG_CERTIFICATE || - bag->type[i] == GNUTLS_BAG_CRL) { + if (bag->element[i].type == GNUTLS_BAG_CERTIFICATE || + bag->element[i].type == GNUTLS_BAG_CRL) { gnutls_datum tmp; /* in that case encode it to a CertBag or * a CrlBag. */ - result = _pkcs12_encode_crt_bag( bag->type[i], &bag->data[i], &tmp); + result = _pkcs12_encode_crt_bag( bag->element[i].type, &bag->element[i].data, &tmp); if (result < 0) { gnutls_assert(); @@ -832,7 +925,7 @@ const char* oid; } else { result = _gnutls_x509_write_value( c2, "?LAST.bagValue", - &bag->data[i], 0); + &bag->element[i].data, 0); } if (result < 0) { diff --git a/lib/x509/pkcs12.h b/lib/x509/pkcs12.h index 97542ff9d2..2c91c9269c 100644 --- a/lib/x509/pkcs12.h +++ b/lib/x509/pkcs12.h @@ -16,9 +16,15 @@ typedef enum gnutls_pkcs12_bag_type { #define MAX_BAG_ELEMENTS 32 +struct bag_element { + gnutls_datum data; + gnutls_pkcs12_bag_type type; + gnutls_datum local_key_id; + char * friendly_name; +}; + typedef struct gnutls_pkcs12_bag_int { - gnutls_datum data[MAX_BAG_ELEMENTS]; - gnutls_pkcs12_bag_type type[MAX_BAG_ELEMENTS]; + struct bag_element element[MAX_BAG_ELEMENTS]; int bag_elements; } gnutls_pkcs12_bag_int; diff --git a/lib/x509/pkcs12_bag.c b/lib/x509/pkcs12_bag.c index 55de2e5954..332fb52c52 100644 --- a/lib/x509/pkcs12_bag.c +++ b/lib/x509/pkcs12_bag.c @@ -54,6 +54,22 @@ int gnutls_pkcs12_bag_init(gnutls_pkcs12_bag * bag) return GNUTLS_E_MEMORY_ERROR; } +static inline +void _pkcs12_bag_free_data( gnutls_pkcs12_bag bag) +{ +int i; + + for (i=0;i<bag->bag_elements;i++) { + _gnutls_free_datum( &bag->element[i].data); + _gnutls_free_datum( &bag->element[i].local_key_id); + gnutls_free( bag->element[i].friendly_name); + bag->element[i].friendly_name = NULL; + bag->element[i].type = 0; + } + +} + + /** * gnutls_pkcs12_bag_deinit - This function deinitializes memory used by a gnutls_pkcs12 structure * @bag: The structure to be initialized @@ -63,10 +79,7 @@ int gnutls_pkcs12_bag_init(gnutls_pkcs12_bag * bag) **/ void gnutls_pkcs12_bag_deinit(gnutls_pkcs12_bag bag) { -int i; - - for (i=0;i<bag->bag_elements;i++) - _gnutls_free_datum( &bag->data[i]); + _pkcs12_bag_free_data( bag); gnutls_free(bag); } @@ -84,7 +97,7 @@ gnutls_pkcs12_bag_type gnutls_pkcs12_bag_get_type(gnutls_pkcs12_bag bag, int ind { if (indx >= bag->bag_elements) return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; - return bag->type[indx]; + return bag->element[indx].type; } /** @@ -113,8 +126,8 @@ int gnutls_pkcs12_bag_get_data(gnutls_pkcs12_bag bag, int indx, gnutls_datum* da if (indx >= bag->bag_elements) return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; - data->data = bag->data[indx].data; - data->size = bag->data[indx].size; + data->data = bag->element[indx].data.data; + data->size = bag->element[indx].data.size; return 0; } @@ -258,7 +271,8 @@ int _pkcs12_encode_crt_bag( gnutls_pkcs12_bag_type type, const gnutls_datum* raw * @data: the data to be copied. * * This function will insert the given data of the given type into the - * bag. + * bag. On success returns the index of the added bag, or a negative + * value on error. * **/ int gnutls_pkcs12_bag_set_data(gnutls_pkcs12_bag bag, gnutls_pkcs12_bag_type type, @@ -277,29 +291,148 @@ int ret; * only one element. */ - if (bag->type[0] == GNUTLS_BAG_PKCS8_KEY || - bag->type[0] == GNUTLS_BAG_PKCS8_ENCRYPTED_KEY || - bag->type[0] == GNUTLS_BAG_ENCRYPTED) { + if (bag->element[0].type == GNUTLS_BAG_PKCS8_KEY || + bag->element[0].type == GNUTLS_BAG_PKCS8_ENCRYPTED_KEY || + bag->element[0].type == GNUTLS_BAG_ENCRYPTED) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } } - ret = _gnutls_set_datum( &bag->data[bag->bag_elements], data->data, data->size); + ret = _gnutls_set_datum( &bag->element[bag->bag_elements].data, data->data, data->size); if (ret < 0) { gnutls_assert(); return ret; } - bag->type[bag->bag_elements] = type; + bag->element[bag->bag_elements].type = type; bag->bag_elements++; + return bag->bag_elements-1; +} + +/** + * gnutls_pkcs12_bag_set_key_id - This function sets a key ID into the bag element + * @bag: The bag + * @indx: The bag's element to add the id + * @id: the ID + * + * This function will add the given key ID, to the specified, by the index, bag + * element. The key ID will be encoded as a 'Local key identifier' bag attribute, + * which is usually used to distinguish the local private key and the certificate pair. + * + * Returns 0 on success, or a negative value on error. + * + **/ +int gnutls_pkcs12_bag_set_key_id(gnutls_pkcs12_bag bag, int indx, + const gnutls_datum* id) +{ +int ret; + + if (indx > bag->bag_elements-1) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + ret = _gnutls_set_datum( &bag->element[indx].local_key_id, + id->data, id->size); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + return 0; } /** + * gnutls_pkcs12_bag_get_key_id - This function gets the key ID from the bag element + * @bag: The bag + * @indx: The bag's element to add the id + * @id: where the ID will be copied (to be treated as const) + * + * This function will return the key ID, of the specified bag element. + * The key ID is usually used to distinguish the local private key and the certificate pair. + * + * Returns 0 on success, or a negative value on error. + * + **/ +int gnutls_pkcs12_bag_get_key_id(gnutls_pkcs12_bag bag, int indx, + gnutls_datum* id) +{ + + if (indx > bag->bag_elements-1) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + id->data = bag->element[indx].local_key_id.data; + id->size = bag->element[indx].local_key_id.size; + + return 0; +} + +/** + * gnutls_pkcs12_bag_get_friendly_name - This function returns the friendly name of the bag element + * @bag: The bag + * @indx: The bag's element to add the id + * @name: will hold a pointer to the name (to be treated as const) + * + * This function will return the friendly name, of the specified bag element. + * The key ID is usually used to distinguish the local private key and the certificate pair. + * + * Returns 0 on success, or a negative value on error. + * + **/ +int gnutls_pkcs12_bag_get_friendly_name(gnutls_pkcs12_bag bag, int indx, + char **name) +{ + if (indx > bag->bag_elements-1) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + *name = bag->element[indx].friendly_name; + + return 0; +} + + +/** + * gnutls_pkcs12_bag_set_friendly_name - This function sets a friendly name into the bag element + * @bag: The bag + * @indx: The bag's element to add the id + * @name: the name + * + * This function will add the given key friendly name, to the specified, by the index, bag + * element. The name will be encoded as a 'Friendly name' bag attribute, + * which is usually used to set a user name to the local private key and the certificate pair. + * + * Returns 0 on success, or a negative value on error. + * + **/ +int gnutls_pkcs12_bag_set_friendly_name(gnutls_pkcs12_bag bag, int indx, + const char* name) +{ + if (indx > bag->bag_elements-1) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + bag->element[indx].friendly_name = gnutls_strdup(name); + + if (name == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + return 0; +} + + +/** * gnutls_pkcs12_bag_decrypt - This function will decrypt an encrypted bag * @bag: The bag * @pass: The password used for encryption @@ -312,13 +445,13 @@ int gnutls_pkcs12_bag_decrypt(gnutls_pkcs12_bag bag, const char* pass) int ret; gnutls_datum dec; - if (bag->type[0] != GNUTLS_BAG_ENCRYPTED) { + if (bag->element[0].type != GNUTLS_BAG_ENCRYPTED) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_pkcs7_decrypt_data( - &bag->data[0], pass, &dec); + &bag->element[0].data, pass, &dec); if (ret < 0) { gnutls_assert(); @@ -329,7 +462,7 @@ gnutls_datum dec; * stuff, and parse it. */ - _gnutls_free_datum( &bag->data[0]); + _gnutls_free_datum( &bag->element[0].data); ret = _pkcs12_decode_safe_contents( &dec, bag); @@ -354,12 +487,12 @@ gnutls_datum dec; **/ int gnutls_pkcs12_bag_encrypt(gnutls_pkcs12_bag bag, const char* pass, unsigned int flags) { -int ret, i; +int ret; ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY; gnutls_datum der = {NULL, 0}; gnutls_datum enc = {NULL, 0}; - if (bag->type[0] == GNUTLS_BAG_ENCRYPTED) { + if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } @@ -398,13 +531,10 @@ gnutls_datum enc = {NULL, 0}; /* encryption succeeded. */ - for (i=0;i<bag->bag_elements;i++) { - _gnutls_free_datum( &bag->data[i]); - bag->type[i] = 0; - } + _pkcs12_bag_free_data( bag); - bag->type[0] = GNUTLS_BAG_ENCRYPTED; - bag->data[0] = enc; + bag->element[0].type = GNUTLS_BAG_ENCRYPTED; + bag->element[0].data = enc; bag->bag_elements = 1; |