summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2003-06-27 07:34:52 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2003-06-27 07:34:52 +0000
commitce784e5c99ddddb454ab402d7ed423c9eee03d3b (patch)
tree39de08ecd2e441cf33cdb795807fa3ab4fb2d0d5
parent202ff857c7b27103756737b433f9bdcb1b805ed1 (diff)
downloadgnutls-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.asn6
-rw-r--r--lib/pkix_asn1_tab.c8
-rw-r--r--lib/x509/common.c3
-rw-r--r--lib/x509/dn.c29
-rw-r--r--lib/x509/pkcs12.c125
-rw-r--r--lib/x509/pkcs12.h10
-rw-r--r--lib/x509/pkcs12_bag.c178
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;