diff options
Diffstat (limited to 'lib/x509/pkcs12.c')
-rw-r--r-- | lib/x509/pkcs12.c | 3002 |
1 files changed, 1457 insertions, 1545 deletions
diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c index f169afeb81..7ccdcc23bc 100644 --- a/lib/x509/pkcs12.c +++ b/lib/x509/pkcs12.c @@ -41,84 +41,81 @@ * which holds them. Returns an ASN1_TYPE of authenticatedSafe. */ static int -_decode_pkcs12_auth_safe (ASN1_TYPE pkcs12, ASN1_TYPE * authen_safe, - gnutls_datum_t * raw) +_decode_pkcs12_auth_safe(ASN1_TYPE pkcs12, ASN1_TYPE * authen_safe, + gnutls_datum_t * raw) { - char oid[MAX_OID_SIZE]; - ASN1_TYPE c2 = ASN1_TYPE_EMPTY; - gnutls_datum_t auth_safe = { NULL, 0 }; - int len, result; - char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; - - len = sizeof (oid) - 1; - result = asn1_read_value (pkcs12, "authSafe.contentType", oid, &len); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - return _gnutls_asn2err (result); - } - - if (strcmp (oid, DATA_OID) != 0) - { - gnutls_assert (); - _gnutls_debug_log ("Unknown PKCS12 Content OID '%s'\n", oid); - return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE; - } - - /* Step 1. Read the content data - */ - - result = - _gnutls_x509_read_string (pkcs12, "authSafe.content", &auth_safe, ASN1_ETYPE_OCTET_STRING); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - - /* Step 2. Extract the authenticatedSafe. - */ - - if ((result = asn1_create_element - (_gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe", - &c2)) != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - result = asn1_der_decoding (&c2, auth_safe.data, auth_safe.size, error_str); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - _gnutls_debug_log ("DER error: %s\n", error_str); - result = _gnutls_asn2err (result); - goto cleanup; - } - - if (raw == NULL) - { - _gnutls_free_datum (&auth_safe); - } - else - { - raw->data = auth_safe.data; - raw->size = auth_safe.size; - } - - if (authen_safe) - *authen_safe = c2; - else - asn1_delete_structure (&c2); - - return 0; - -cleanup: - if (c2) - asn1_delete_structure (&c2); - _gnutls_free_datum (&auth_safe); - return result; + char oid[MAX_OID_SIZE]; + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; + gnutls_datum_t auth_safe = { NULL, 0 }; + int len, result; + char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; + + len = sizeof(oid) - 1; + result = + asn1_read_value(pkcs12, "authSafe.contentType", oid, &len); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + if (strcmp(oid, DATA_OID) != 0) { + gnutls_assert(); + _gnutls_debug_log("Unknown PKCS12 Content OID '%s'\n", + oid); + return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE; + } + + /* Step 1. Read the content data + */ + + result = + _gnutls_x509_read_string(pkcs12, "authSafe.content", + &auth_safe, ASN1_ETYPE_OCTET_STRING); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + /* Step 2. Extract the authenticatedSafe. + */ + + if ((result = asn1_create_element + (_gnutls_get_pkix(), "PKIX1.pkcs-12-AuthenticatedSafe", + &c2)) != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + result = + asn1_der_decoding(&c2, auth_safe.data, auth_safe.size, + error_str); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + _gnutls_debug_log("DER error: %s\n", error_str); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if (raw == NULL) { + _gnutls_free_datum(&auth_safe); + } else { + raw->data = auth_safe.data; + raw->size = auth_safe.size; + } + + if (authen_safe) + *authen_safe = c2; + else + asn1_delete_structure(&c2); + + return 0; + + cleanup: + if (c2) + asn1_delete_structure(&c2); + _gnutls_free_datum(&auth_safe); + return result; } /** @@ -132,25 +129,22 @@ cleanup: * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ -int -gnutls_pkcs12_init (gnutls_pkcs12_t * pkcs12) +int gnutls_pkcs12_init(gnutls_pkcs12_t * pkcs12) { - *pkcs12 = gnutls_calloc (1, sizeof (gnutls_pkcs12_int)); - - if (*pkcs12) - { - int result = asn1_create_element (_gnutls_get_pkix (), - "PKIX1.pkcs-12-PFX", - &(*pkcs12)->pkcs12); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - gnutls_free (*pkcs12); - return _gnutls_asn2err (result); - } - return 0; /* success */ - } - return GNUTLS_E_MEMORY_ERROR; + *pkcs12 = gnutls_calloc(1, sizeof(gnutls_pkcs12_int)); + + if (*pkcs12) { + int result = asn1_create_element(_gnutls_get_pkix(), + "PKIX1.pkcs-12-PFX", + &(*pkcs12)->pkcs12); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + gnutls_free(*pkcs12); + return _gnutls_asn2err(result); + } + return 0; /* success */ + } + return GNUTLS_E_MEMORY_ERROR; } /** @@ -159,16 +153,15 @@ gnutls_pkcs12_init (gnutls_pkcs12_t * pkcs12) * * This function will deinitialize a PKCS12 structure. **/ -void -gnutls_pkcs12_deinit (gnutls_pkcs12_t pkcs12) +void gnutls_pkcs12_deinit(gnutls_pkcs12_t pkcs12) { - if (!pkcs12) - return; + if (!pkcs12) + return; - if (pkcs12->pkcs12) - asn1_delete_structure (&pkcs12->pkcs12); + if (pkcs12->pkcs12) + asn1_delete_structure(&pkcs12->pkcs12); - gnutls_free (pkcs12); + gnutls_free(pkcs12); } /** @@ -187,58 +180,56 @@ gnutls_pkcs12_deinit (gnutls_pkcs12_t pkcs12) * negative error value. **/ int -gnutls_pkcs12_import (gnutls_pkcs12_t pkcs12, - const gnutls_datum_t * data, - gnutls_x509_crt_fmt_t format, unsigned int flags) +gnutls_pkcs12_import(gnutls_pkcs12_t pkcs12, + const gnutls_datum_t * data, + gnutls_x509_crt_fmt_t format, unsigned int flags) { - int result = 0, need_free = 0; - gnutls_datum_t _data; - char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; - - _data.data = data->data; - _data.size = data->size; - - if (pkcs12 == NULL) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - /* If the PKCS12 is in PEM format then decode it - */ - if (format == GNUTLS_X509_FMT_PEM) - { - result = _gnutls_fbase64_decode (PEM_PKCS12, data->data, data->size, - &_data); - - if (result < 0) - { - gnutls_assert (); - return result; - } - - need_free = 1; - } - - result = - asn1_der_decoding (&pkcs12->pkcs12, _data.data, _data.size, error_str); - if (result != ASN1_SUCCESS) - { - result = _gnutls_asn2err (result); - _gnutls_debug_log ("DER error: %s\n", error_str); - gnutls_assert (); - goto cleanup; - } - - if (need_free) - _gnutls_free_datum (&_data); - - return 0; - -cleanup: - if (need_free) - _gnutls_free_datum (&_data); - return result; + int result = 0, need_free = 0; + gnutls_datum_t _data; + char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; + + _data.data = data->data; + _data.size = data->size; + + if (pkcs12 == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + /* If the PKCS12 is in PEM format then decode it + */ + if (format == GNUTLS_X509_FMT_PEM) { + result = + _gnutls_fbase64_decode(PEM_PKCS12, data->data, + data->size, &_data); + + if (result < 0) { + gnutls_assert(); + return result; + } + + need_free = 1; + } + + result = + asn1_der_decoding(&pkcs12->pkcs12, _data.data, _data.size, + error_str); + if (result != ASN1_SUCCESS) { + result = _gnutls_asn2err(result); + _gnutls_debug_log("DER error: %s\n", error_str); + gnutls_assert(); + goto cleanup; + } + + if (need_free) + _gnutls_free_datum(&_data); + + return 0; + + cleanup: + if (need_free) + _gnutls_free_datum(&_data); + return result; } @@ -263,18 +254,17 @@ cleanup: * returned, and 0 on success. **/ int -gnutls_pkcs12_export (gnutls_pkcs12_t pkcs12, - gnutls_x509_crt_fmt_t format, void *output_data, - size_t * output_data_size) +gnutls_pkcs12_export(gnutls_pkcs12_t pkcs12, + gnutls_x509_crt_fmt_t format, void *output_data, + size_t * output_data_size) { - if (pkcs12 == NULL) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - return _gnutls_x509_export_int (pkcs12->pkcs12, format, PEM_PKCS12, - output_data, output_data_size); + if (pkcs12 == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + return _gnutls_x509_export_int(pkcs12->pkcs12, format, PEM_PKCS12, + output_data, output_data_size); } /** @@ -296,281 +286,276 @@ gnutls_pkcs12_export (gnutls_pkcs12_t pkcs12, * Since: 3.1.3 **/ int -gnutls_pkcs12_export2 (gnutls_pkcs12_t pkcs12, - gnutls_x509_crt_fmt_t format, gnutls_datum_t *out) +gnutls_pkcs12_export2(gnutls_pkcs12_t pkcs12, + gnutls_x509_crt_fmt_t format, gnutls_datum_t * out) { - if (pkcs12 == NULL) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } + if (pkcs12 == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } - return _gnutls_x509_export_int2 (pkcs12->pkcs12, format, PEM_PKCS12, out); + return _gnutls_x509_export_int2(pkcs12->pkcs12, format, PEM_PKCS12, + out); } -static int -oid2bag (const char *oid) +static int oid2bag(const char *oid) { - if (strcmp (oid, BAG_PKCS8_KEY) == 0) - return GNUTLS_BAG_PKCS8_KEY; - if (strcmp (oid, BAG_PKCS8_ENCRYPTED_KEY) == 0) - return GNUTLS_BAG_PKCS8_ENCRYPTED_KEY; - if (strcmp (oid, BAG_CERTIFICATE) == 0) - return GNUTLS_BAG_CERTIFICATE; - if (strcmp (oid, BAG_CRL) == 0) - return GNUTLS_BAG_CRL; - if (strcmp (oid, BAG_SECRET) == 0) - return GNUTLS_BAG_SECRET; - - return GNUTLS_BAG_UNKNOWN; + if (strcmp(oid, BAG_PKCS8_KEY) == 0) + return GNUTLS_BAG_PKCS8_KEY; + if (strcmp(oid, BAG_PKCS8_ENCRYPTED_KEY) == 0) + return GNUTLS_BAG_PKCS8_ENCRYPTED_KEY; + if (strcmp(oid, BAG_CERTIFICATE) == 0) + return GNUTLS_BAG_CERTIFICATE; + if (strcmp(oid, BAG_CRL) == 0) + return GNUTLS_BAG_CRL; + if (strcmp(oid, BAG_SECRET) == 0) + return GNUTLS_BAG_SECRET; + + return GNUTLS_BAG_UNKNOWN; } -static const char * -bag_to_oid (int bag) +static const char *bag_to_oid(int bag) { - switch (bag) - { - case GNUTLS_BAG_PKCS8_KEY: - return BAG_PKCS8_KEY; - case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY: - return BAG_PKCS8_ENCRYPTED_KEY; - case GNUTLS_BAG_CERTIFICATE: - return BAG_CERTIFICATE; - case GNUTLS_BAG_CRL: - return BAG_CRL; - case GNUTLS_BAG_SECRET: - return BAG_SECRET; - } - return NULL; + switch (bag) { + case GNUTLS_BAG_PKCS8_KEY: + return BAG_PKCS8_KEY; + case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY: + return BAG_PKCS8_ENCRYPTED_KEY; + case GNUTLS_BAG_CERTIFICATE: + return BAG_CERTIFICATE; + case GNUTLS_BAG_CRL: + return BAG_CRL; + case GNUTLS_BAG_SECRET: + return BAG_SECRET; + } + return NULL; } /* Decodes the SafeContents, and puts the output in * the given bag. */ int -_pkcs12_decode_safe_contents (const gnutls_datum_t * content, - gnutls_pkcs12_bag_t bag) +_pkcs12_decode_safe_contents(const gnutls_datum_t * content, + gnutls_pkcs12_bag_t bag) { - char oid[MAX_OID_SIZE], root[ASN1_MAX_NAME_SIZE]; - ASN1_TYPE c2 = ASN1_TYPE_EMPTY; - int len, result; - int bag_type; - gnutls_datum_t attr_val; - gnutls_datum_t t; - int count = 0, i, attributes, j; - - /* Step 1. Extract the SEQUENCE. - */ - - if ((result = asn1_create_element - (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents", - &c2)) != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - result = asn1_der_decoding (&c2, content->data, content->size, NULL); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - /* Count the number of bags - */ - result = asn1_number_of_elements (c2, "", &count); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - bag->bag_elements = MIN (MAX_BAG_ELEMENTS, count); - - for (i = 0; i < bag->bag_elements; i++) - { - - snprintf (root, sizeof (root), "?%u.bagId", i + 1); - - len = sizeof (oid); - result = asn1_read_value (c2, root, oid, &len); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - /* Read the Bag type - */ - bag_type = oid2bag (oid); - - if (bag_type < 0) - { - gnutls_assert (); - goto cleanup; - } - - /* Read the Bag Value - */ - - snprintf (root, sizeof (root), "?%u.bagValue", i + 1); - - result = _gnutls_x509_read_value (c2, root, &bag->element[i].data); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - - if (bag_type == GNUTLS_BAG_CERTIFICATE || bag_type == GNUTLS_BAG_CRL - || bag_type == GNUTLS_BAG_SECRET) - { - gnutls_datum_t tmp = bag->element[i].data; - - result = - _pkcs12_decode_crt_bag (bag_type, &tmp, &bag->element[i].data); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - - _gnutls_free_datum (&tmp); - } - - /* read the bag attributes - */ - snprintf (root, sizeof (root), "?%u.bagAttributes", i + 1); - - result = asn1_number_of_elements (c2, root, &attributes); - if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - if (attributes < 0) - attributes = 1; - - if (result != ASN1_ELEMENT_NOT_FOUND) - for (j = 0; j < attributes; j++) - { - - snprintf (root, sizeof (root), "?%u.bagAttributes.?%u", i + 1, - j + 1); - - result = - _gnutls_x509_decode_and_read_attribute (c2, root, oid, - sizeof (oid), &attr_val, - 1, 0); - - if (result < 0) - { - gnutls_assert (); - continue; /* continue in case we find some known attributes */ - } - - if (strcmp (oid, KEY_ID_OID) == 0) - { - result = - _gnutls_x509_decode_string (ASN1_ETYPE_OCTET_STRING, attr_val.data, - attr_val.size, &t); - _gnutls_free_datum (&attr_val); - if (result < 0) - { - gnutls_assert (); - _gnutls_debug_log - ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid); - continue; - } - - attr_val.data = t.data; - attr_val.size = t.size; - - bag->element[i].local_key_id = attr_val; - } - else if (strcmp (oid, FRIENDLY_NAME_OID) == 0) - { - result = - _gnutls_x509_decode_string (ASN1_ETYPE_BMP_STRING, - attr_val.data, attr_val.size, &t); - _gnutls_free_datum (&attr_val); - if (result < 0) - { - gnutls_assert (); - _gnutls_debug_log - ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid); - continue; - } - - attr_val.data = t.data; - attr_val.size = t.size; - - bag->element[i].friendly_name = (char*)t.data; - } - else - { - _gnutls_free_datum (&attr_val); - _gnutls_debug_log - ("Unknown PKCS12 Bag Attribute OID '%s'\n", oid); - } - } - - - bag->element[i].type = bag_type; - - } - - asn1_delete_structure (&c2); - - - return 0; - -cleanup: - if (c2) - asn1_delete_structure (&c2); - return result; + char oid[MAX_OID_SIZE], root[ASN1_MAX_NAME_SIZE]; + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; + int len, result; + int bag_type; + gnutls_datum_t attr_val; + gnutls_datum_t t; + int count = 0, i, attributes, j; + + /* Step 1. Extract the SEQUENCE. + */ + + if ((result = asn1_create_element + (_gnutls_get_pkix(), "PKIX1.pkcs-12-SafeContents", + &c2)) != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + result = + asn1_der_decoding(&c2, content->data, content->size, NULL); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + /* Count the number of bags + */ + result = asn1_number_of_elements(c2, "", &count); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + bag->bag_elements = MIN(MAX_BAG_ELEMENTS, count); + + for (i = 0; i < bag->bag_elements; i++) { + + snprintf(root, sizeof(root), "?%u.bagId", i + 1); + + len = sizeof(oid); + result = asn1_read_value(c2, root, oid, &len); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + /* Read the Bag type + */ + bag_type = oid2bag(oid); + + if (bag_type < 0) { + gnutls_assert(); + goto cleanup; + } + + /* Read the Bag Value + */ + + snprintf(root, sizeof(root), "?%u.bagValue", i + 1); + + result = + _gnutls_x509_read_value(c2, root, + &bag->element[i].data); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + if (bag_type == GNUTLS_BAG_CERTIFICATE + || bag_type == GNUTLS_BAG_CRL + || bag_type == GNUTLS_BAG_SECRET) { + gnutls_datum_t tmp = bag->element[i].data; + + result = + _pkcs12_decode_crt_bag(bag_type, &tmp, + &bag->element[i].data); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + _gnutls_free_datum(&tmp); + } + + /* read the bag attributes + */ + snprintf(root, sizeof(root), "?%u.bagAttributes", i + 1); + + result = asn1_number_of_elements(c2, root, &attributes); + if (result != ASN1_SUCCESS + && result != ASN1_ELEMENT_NOT_FOUND) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if (attributes < 0) + attributes = 1; + + if (result != ASN1_ELEMENT_NOT_FOUND) + for (j = 0; j < attributes; j++) { + + snprintf(root, sizeof(root), + "?%u.bagAttributes.?%u", i + 1, + j + 1); + + result = + _gnutls_x509_decode_and_read_attribute + (c2, root, oid, sizeof(oid), &attr_val, + 1, 0); + + if (result < 0) { + gnutls_assert(); + continue; /* continue in case we find some known attributes */ + } + + if (strcmp(oid, KEY_ID_OID) == 0) { + result = + _gnutls_x509_decode_string + (ASN1_ETYPE_OCTET_STRING, + attr_val.data, attr_val.size, + &t); + _gnutls_free_datum(&attr_val); + if (result < 0) { + gnutls_assert(); + _gnutls_debug_log + ("Error decoding PKCS12 Bag Attribute OID '%s'\n", + oid); + continue; + } + + attr_val.data = t.data; + attr_val.size = t.size; + + bag->element[i].local_key_id = + attr_val; + } else if (strcmp(oid, FRIENDLY_NAME_OID) + == 0) { + result = + _gnutls_x509_decode_string + (ASN1_ETYPE_BMP_STRING, + attr_val.data, attr_val.size, + &t); + _gnutls_free_datum(&attr_val); + if (result < 0) { + gnutls_assert(); + _gnutls_debug_log + ("Error decoding PKCS12 Bag Attribute OID '%s'\n", + oid); + continue; + } + + attr_val.data = t.data; + attr_val.size = t.size; + + bag->element[i].friendly_name = + (char *) t.data; + } else { + _gnutls_free_datum(&attr_val); + _gnutls_debug_log + ("Unknown PKCS12 Bag Attribute OID '%s'\n", + oid); + } + } + + + bag->element[i].type = bag_type; + + } + + asn1_delete_structure(&c2); + + + return 0; + + cleanup: + if (c2) + asn1_delete_structure(&c2); + return result; } static int -_parse_safe_contents (ASN1_TYPE sc, const char *sc_name, - gnutls_pkcs12_bag_t bag) +_parse_safe_contents(ASN1_TYPE sc, const char *sc_name, + gnutls_pkcs12_bag_t bag) { - gnutls_datum_t content = { NULL, 0 }; - int result; + gnutls_datum_t content = { NULL, 0 }; + int result; - /* Step 1. Extract the content. - */ + /* Step 1. Extract the content. + */ - result = _gnutls_x509_read_string (sc, sc_name, &content, ASN1_ETYPE_OCTET_STRING); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } + result = + _gnutls_x509_read_string(sc, sc_name, &content, + ASN1_ETYPE_OCTET_STRING); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } - result = _pkcs12_decode_safe_contents (&content, bag); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } + result = _pkcs12_decode_safe_contents(&content, bag); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } - _gnutls_free_datum (&content); + _gnutls_free_datum(&content); - return 0; + return 0; -cleanup: - _gnutls_free_datum (&content); - return result; + cleanup: + _gnutls_free_datum(&content); + return result; } @@ -589,137 +574,128 @@ cleanup: * negative error value. **/ int -gnutls_pkcs12_get_bag (gnutls_pkcs12_t pkcs12, - int indx, gnutls_pkcs12_bag_t bag) +gnutls_pkcs12_get_bag(gnutls_pkcs12_t pkcs12, + int indx, gnutls_pkcs12_bag_t bag) { - ASN1_TYPE c2 = ASN1_TYPE_EMPTY; - int result, len; - char root2[ASN1_MAX_NAME_SIZE]; - char oid[MAX_OID_SIZE]; - - if (pkcs12 == NULL) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - /* Step 1. decode the data. - */ - result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL); - if (result < 0) - { - gnutls_assert (); - return result; - } - - /* Step 2. Parse the AuthenticatedSafe - */ - - snprintf (root2, sizeof (root2), "?%u.contentType", indx + 1); - - len = sizeof (oid) - 1; - result = asn1_read_value (c2, root2, oid, &len); - - if (result == ASN1_ELEMENT_NOT_FOUND) - { - result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; - goto cleanup; - } - - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - /* Not encrypted Bag - */ - - snprintf (root2, sizeof (root2), "?%u.content", indx + 1); - - if (strcmp (oid, DATA_OID) == 0) - { - result = _parse_safe_contents (c2, root2, bag); - goto cleanup; - } - - /* ENC_DATA_OID needs decryption */ - - bag->element[0].type = GNUTLS_BAG_ENCRYPTED; - bag->bag_elements = 1; - - result = _gnutls_x509_read_value (c2, root2, &bag->element[0].data); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - - result = 0; - -cleanup: - if (c2) - asn1_delete_structure (&c2); - return result; + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; + int result, len; + char root2[ASN1_MAX_NAME_SIZE]; + char oid[MAX_OID_SIZE]; + + if (pkcs12 == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + /* Step 1. decode the data. + */ + result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, &c2, NULL); + if (result < 0) { + gnutls_assert(); + return result; + } + + /* Step 2. Parse the AuthenticatedSafe + */ + + snprintf(root2, sizeof(root2), "?%u.contentType", indx + 1); + + len = sizeof(oid) - 1; + result = asn1_read_value(c2, root2, oid, &len); + + if (result == ASN1_ELEMENT_NOT_FOUND) { + result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + goto cleanup; + } + + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + /* Not encrypted Bag + */ + + snprintf(root2, sizeof(root2), "?%u.content", indx + 1); + + if (strcmp(oid, DATA_OID) == 0) { + result = _parse_safe_contents(c2, root2, bag); + goto cleanup; + } + + /* ENC_DATA_OID needs decryption */ + + bag->element[0].type = GNUTLS_BAG_ENCRYPTED; + bag->bag_elements = 1; + + result = _gnutls_x509_read_value(c2, root2, &bag->element[0].data); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + result = 0; + + cleanup: + if (c2) + asn1_delete_structure(&c2); + return result; } /* Creates an empty PFX structure for the PKCS12 structure. */ -static int -create_empty_pfx (ASN1_TYPE pkcs12) +static int create_empty_pfx(ASN1_TYPE pkcs12) { - uint8_t three = 3; - int result; - ASN1_TYPE c2 = ASN1_TYPE_EMPTY; - - /* Use version 3 - */ - result = asn1_write_value (pkcs12, "version", &three, 1); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - /* Write the content type of the data - */ - result = asn1_write_value (pkcs12, "authSafe.contentType", DATA_OID, 1); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - /* Check if the authenticatedSafe content is empty, and encode a - * null one in that case. - */ - - if ((result = asn1_create_element - (_gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe", - &c2)) != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - result = - _gnutls_x509_der_encode_and_copy (c2, "", pkcs12, "authSafe.content", 1); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - asn1_delete_structure (&c2); - - return 0; - -cleanup: - asn1_delete_structure (&c2); - return result; + uint8_t three = 3; + int result; + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; + + /* Use version 3 + */ + result = asn1_write_value(pkcs12, "version", &three, 1); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + /* Write the content type of the data + */ + result = + asn1_write_value(pkcs12, "authSafe.contentType", DATA_OID, 1); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + /* Check if the authenticatedSafe content is empty, and encode a + * null one in that case. + */ + + if ((result = asn1_create_element + (_gnutls_get_pkix(), "PKIX1.pkcs-12-AuthenticatedSafe", + &c2)) != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + result = + _gnutls_x509_der_encode_and_copy(c2, "", pkcs12, + "authSafe.content", 1); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + asn1_delete_structure(&c2); + + return 0; + + cleanup: + asn1_delete_structure(&c2); + return result; } @@ -733,126 +709,117 @@ cleanup: * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ -int -gnutls_pkcs12_set_bag (gnutls_pkcs12_t pkcs12, gnutls_pkcs12_bag_t bag) +int gnutls_pkcs12_set_bag(gnutls_pkcs12_t pkcs12, gnutls_pkcs12_bag_t bag) { - ASN1_TYPE c2 = ASN1_TYPE_EMPTY; - ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY; - int result; - int enc = 0, dum = 1; - char null; - - if (pkcs12 == NULL) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - /* Step 1. Check if the pkcs12 structure is empty. In that - * case generate an empty PFX. - */ - result = asn1_read_value (pkcs12->pkcs12, "authSafe.content", &null, &dum); - if (result == ASN1_VALUE_NOT_FOUND) - { - result = create_empty_pfx (pkcs12->pkcs12); - if (result < 0) - { - gnutls_assert (); - return result; - } - } - - /* Step 2. decode the authenticatedSafe. - */ - result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL); - if (result < 0) - { - gnutls_assert (); - return result; - } - - /* Step 3. Encode the bag elements into a SafeContents - * structure. - */ - result = _pkcs12_encode_safe_contents (bag, &safe_cont, &enc); - if (result < 0) - { - gnutls_assert (); - return result; - } - - /* Step 4. Insert the encoded SafeContents into the AuthenticatedSafe - * structure. - */ - result = asn1_write_value (c2, "", "NEW", 1); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - if (enc) - result = asn1_write_value (c2, "?LAST.contentType", ENC_DATA_OID, 1); - else - result = asn1_write_value (c2, "?LAST.contentType", DATA_OID, 1); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - if (enc) - { - /* Encrypted packets are written directly. - */ - 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); - goto cleanup; - } - } - else - { - result = - _gnutls_x509_der_encode_and_copy (safe_cont, "", c2, - "?LAST.content", 1); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - } - - asn1_delete_structure (&safe_cont); - - - /* Step 5. Reencode and copy the AuthenticatedSafe into the pkcs12 - * structure. - */ - result = - _gnutls_x509_der_encode_and_copy (c2, "", pkcs12->pkcs12, - "authSafe.content", 1); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - - asn1_delete_structure (&c2); - - return 0; - -cleanup: - asn1_delete_structure (&c2); - asn1_delete_structure (&safe_cont); - return result; + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; + ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY; + int result; + int enc = 0, dum = 1; + char null; + + if (pkcs12 == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + /* Step 1. Check if the pkcs12 structure is empty. In that + * case generate an empty PFX. + */ + result = + asn1_read_value(pkcs12->pkcs12, "authSafe.content", &null, + &dum); + if (result == ASN1_VALUE_NOT_FOUND) { + result = create_empty_pfx(pkcs12->pkcs12); + if (result < 0) { + gnutls_assert(); + return result; + } + } + + /* Step 2. decode the authenticatedSafe. + */ + result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, &c2, NULL); + if (result < 0) { + gnutls_assert(); + return result; + } + + /* Step 3. Encode the bag elements into a SafeContents + * structure. + */ + result = _pkcs12_encode_safe_contents(bag, &safe_cont, &enc); + if (result < 0) { + gnutls_assert(); + return result; + } + + /* Step 4. Insert the encoded SafeContents into the AuthenticatedSafe + * structure. + */ + result = asn1_write_value(c2, "", "NEW", 1); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if (enc) + result = + asn1_write_value(c2, "?LAST.contentType", ENC_DATA_OID, + 1); + else + result = + asn1_write_value(c2, "?LAST.contentType", DATA_OID, 1); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if (enc) { + /* Encrypted packets are written directly. + */ + 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); + goto cleanup; + } + } else { + result = + _gnutls_x509_der_encode_and_copy(safe_cont, "", c2, + "?LAST.content", 1); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + } + + asn1_delete_structure(&safe_cont); + + + /* Step 5. Reencode and copy the AuthenticatedSafe into the pkcs12 + * structure. + */ + result = + _gnutls_x509_der_encode_and_copy(c2, "", pkcs12->pkcs12, + "authSafe.content", 1); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + asn1_delete_structure(&c2); + + return 0; + + cleanup: + asn1_delete_structure(&c2); + asn1_delete_structure(&safe_cont); + return result; } /** @@ -865,128 +832,119 @@ cleanup: * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ -int -gnutls_pkcs12_generate_mac (gnutls_pkcs12_t pkcs12, const char *pass) +int gnutls_pkcs12_generate_mac(gnutls_pkcs12_t pkcs12, const char *pass) { - uint8_t salt[8], key[20]; - int result; - const int iter = 1; - mac_hd_st td1; - gnutls_datum_t tmp = { NULL, 0 }; - uint8_t sha_mac[20]; - - if (pkcs12 == NULL) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - /* Generate the salt. - */ - result = _gnutls_rnd (GNUTLS_RND_NONCE, salt, sizeof (salt)); - if (result < 0) - { - gnutls_assert (); - return result; - } - - /* Write the salt into the structure. - */ - result = - asn1_write_value (pkcs12->pkcs12, "macData.macSalt", salt, sizeof (salt)); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - /* write the iterations - */ - - if (iter > 1) - { - result = - _gnutls_x509_write_uint32 (pkcs12->pkcs12, "macData.iterations", - iter); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - } - - /* Generate the key. - */ - result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt, sizeof (salt), - iter, pass, sizeof (key), key); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - - /* Get the data to be MACed - */ - result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - - /* MAC the data - */ - result = _gnutls_mac_init (&td1, mac_to_entry(GNUTLS_MAC_SHA1), - key, sizeof (key)); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - - _gnutls_mac (&td1, tmp.data, tmp.size); - _gnutls_free_datum (&tmp); - - _gnutls_mac_deinit (&td1, sha_mac); - - - result = - asn1_write_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac, - sizeof (sha_mac)); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - result = - asn1_write_value (pkcs12->pkcs12, - "macData.mac.digestAlgorithm.parameters", NULL, 0); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - result = - asn1_write_value (pkcs12->pkcs12, - "macData.mac.digestAlgorithm.algorithm", HASH_OID_SHA1, - 1); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - return 0; - -cleanup: - _gnutls_free_datum (&tmp); - return result; + uint8_t salt[8], key[20]; + int result; + const int iter = 1; + mac_hd_st td1; + gnutls_datum_t tmp = { NULL, 0 }; + uint8_t sha_mac[20]; + + if (pkcs12 == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + /* Generate the salt. + */ + result = _gnutls_rnd(GNUTLS_RND_NONCE, salt, sizeof(salt)); + if (result < 0) { + gnutls_assert(); + return result; + } + + /* Write the salt into the structure. + */ + result = + asn1_write_value(pkcs12->pkcs12, "macData.macSalt", salt, + sizeof(salt)); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + /* write the iterations + */ + + if (iter > 1) { + result = + _gnutls_x509_write_uint32(pkcs12->pkcs12, + "macData.iterations", iter); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + } + + /* Generate the key. + */ + result = + _gnutls_pkcs12_string_to_key(3 /*MAC*/, salt, sizeof(salt), + iter, pass, sizeof(key), key); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + /* Get the data to be MACed + */ + result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, NULL, &tmp); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + /* MAC the data + */ + result = _gnutls_mac_init(&td1, mac_to_entry(GNUTLS_MAC_SHA1), + key, sizeof(key)); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + _gnutls_mac(&td1, tmp.data, tmp.size); + _gnutls_free_datum(&tmp); + + _gnutls_mac_deinit(&td1, sha_mac); + + + result = + asn1_write_value(pkcs12->pkcs12, "macData.mac.digest", sha_mac, + sizeof(sha_mac)); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + result = + asn1_write_value(pkcs12->pkcs12, + "macData.mac.digestAlgorithm.parameters", + NULL, 0); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + result = + asn1_write_value(pkcs12->pkcs12, + "macData.mac.digestAlgorithm.algorithm", + HASH_OID_SHA1, 1); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + return 0; + + cleanup: + _gnutls_free_datum(&tmp); + return result; } /** @@ -999,216 +957,201 @@ cleanup: * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ -int -gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass) +int gnutls_pkcs12_verify_mac(gnutls_pkcs12_t pkcs12, const char *pass) { - uint8_t key[20]; - int result; - unsigned int iter; - int len; - mac_hd_st td1; - gnutls_datum_t tmp = { NULL, 0 }, salt = - { - NULL, 0}; - uint8_t sha_mac[20]; - uint8_t sha_mac_orig[20]; - - if (pkcs12 == NULL) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - /* read the iterations - */ - - result = - _gnutls_x509_read_uint (pkcs12->pkcs12, "macData.iterations", &iter); - if (result < 0) - { - iter = 1; /* the default */ - } - - - /* Read the salt from the structure. - */ - result = - _gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - /* Generate the key. - */ - result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt.data, salt.size, - iter, pass, sizeof (key), key); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - - _gnutls_free_datum (&salt); - - /* Get the data to be MACed - */ - result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - - /* MAC the data - */ - result = _gnutls_mac_init (&td1, mac_to_entry(GNUTLS_MAC_SHA1), - key, sizeof (key)); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - - _gnutls_mac (&td1, tmp.data, tmp.size); - _gnutls_free_datum (&tmp); - - _gnutls_mac_deinit (&td1, sha_mac); - - len = sizeof (sha_mac_orig); - result = - asn1_read_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac_orig, - &len); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - if (memcmp (sha_mac_orig, sha_mac, sizeof (sha_mac)) != 0) - { - gnutls_assert (); - return GNUTLS_E_MAC_VERIFY_FAILED; - } - - return 0; - -cleanup: - _gnutls_free_datum (&tmp); - _gnutls_free_datum (&salt); - return result; + uint8_t key[20]; + int result; + unsigned int iter; + int len; + mac_hd_st td1; + gnutls_datum_t tmp = { NULL, 0 }, salt = { + NULL, 0}; + uint8_t sha_mac[20]; + uint8_t sha_mac_orig[20]; + + if (pkcs12 == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + /* read the iterations + */ + + result = + _gnutls_x509_read_uint(pkcs12->pkcs12, "macData.iterations", + &iter); + if (result < 0) { + iter = 1; /* the default */ + } + + + /* Read the salt from the structure. + */ + result = + _gnutls_x509_read_value(pkcs12->pkcs12, "macData.macSalt", + &salt); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + /* Generate the key. + */ + result = + _gnutls_pkcs12_string_to_key(3 /*MAC*/, salt.data, salt.size, + iter, pass, sizeof(key), key); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + _gnutls_free_datum(&salt); + + /* Get the data to be MACed + */ + result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, NULL, &tmp); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + /* MAC the data + */ + result = _gnutls_mac_init(&td1, mac_to_entry(GNUTLS_MAC_SHA1), + key, sizeof(key)); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + _gnutls_mac(&td1, tmp.data, tmp.size); + _gnutls_free_datum(&tmp); + + _gnutls_mac_deinit(&td1, sha_mac); + + len = sizeof(sha_mac_orig); + result = + asn1_read_value(pkcs12->pkcs12, "macData.mac.digest", + sha_mac_orig, &len); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if (memcmp(sha_mac_orig, sha_mac, sizeof(sha_mac)) != 0) { + gnutls_assert(); + return GNUTLS_E_MAC_VERIFY_FAILED; + } + + return 0; + + cleanup: + _gnutls_free_datum(&tmp); + _gnutls_free_datum(&salt); + return result; } static int -write_attributes (gnutls_pkcs12_bag_t bag, int elem, - ASN1_TYPE c2, const char *where) +write_attributes(gnutls_pkcs12_bag_t 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) - { - uint8_t *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; + 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) { + uint8_t *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; } @@ -1216,125 +1159,118 @@ write_attributes (gnutls_pkcs12_bag_t bag, int elem, * the given datum. Enc is set to non-zero if the data are encrypted; */ int -_pkcs12_encode_safe_contents (gnutls_pkcs12_bag_t bag, ASN1_TYPE * contents, - int *enc) +_pkcs12_encode_safe_contents(gnutls_pkcs12_bag_t bag, ASN1_TYPE * contents, + int *enc) { - ASN1_TYPE c2 = ASN1_TYPE_EMPTY; - int result; - int i; - const char *oid; - - if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc) - { - *enc = 1; - return 0; /* ENCRYPTED BAG, do nothing. */ - } - else if (enc) - *enc = 0; - - /* Step 1. Create the SEQUENCE. - */ - - if ((result = asn1_create_element - (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents", - &c2)) != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - for (i = 0; i < bag->bag_elements; i++) - { - - oid = bag_to_oid (bag->element[i].type); - if (oid == NULL) - { - gnutls_assert (); - continue; - } - - result = asn1_write_value (c2, "", "NEW", 1); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - /* Copy the bag type. - */ - result = asn1_write_value (c2, "?LAST.bagId", oid, 1); - if (result != ASN1_SUCCESS) - { - gnutls_assert (); - result = _gnutls_asn2err (result); - goto cleanup; - } - - /* Set empty attributes - */ - result = write_attributes (bag, i, c2, "?LAST.bagAttributes"); - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - - - /* Copy the Bag Value - */ - - if (bag->element[i].type == GNUTLS_BAG_CERTIFICATE || - bag->element[i].type == GNUTLS_BAG_SECRET || - bag->element[i].type == GNUTLS_BAG_CRL) - { - gnutls_datum_t tmp; - - /* in that case encode it to a CertBag or - * a CrlBag. - */ - - result = - _pkcs12_encode_crt_bag (bag->element[i].type, - &bag->element[i].data, &tmp); - - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - - result = _gnutls_x509_write_value (c2, "?LAST.bagValue", &tmp); - - _gnutls_free_datum (&tmp); - - } - else - { - - result = _gnutls_x509_write_value (c2, "?LAST.bagValue", - &bag->element[i].data); - } - - if (result < 0) - { - gnutls_assert (); - goto cleanup; - } - - } - - /* Encode the data and copy them into the datum - */ - *contents = c2; - - return 0; - -cleanup: - if (c2) - asn1_delete_structure (&c2); - return result; + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; + int result; + int i; + const char *oid; + + if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc) { + *enc = 1; + return 0; /* ENCRYPTED BAG, do nothing. */ + } else if (enc) + *enc = 0; + + /* Step 1. Create the SEQUENCE. + */ + + if ((result = asn1_create_element + (_gnutls_get_pkix(), "PKIX1.pkcs-12-SafeContents", + &c2)) != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + for (i = 0; i < bag->bag_elements; i++) { + + oid = bag_to_oid(bag->element[i].type); + if (oid == NULL) { + gnutls_assert(); + continue; + } + + result = asn1_write_value(c2, "", "NEW", 1); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + /* Copy the bag type. + */ + result = asn1_write_value(c2, "?LAST.bagId", oid, 1); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + /* Set empty attributes + */ + result = + write_attributes(bag, i, c2, "?LAST.bagAttributes"); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + + /* Copy the Bag Value + */ + + if (bag->element[i].type == GNUTLS_BAG_CERTIFICATE || + bag->element[i].type == GNUTLS_BAG_SECRET || + bag->element[i].type == GNUTLS_BAG_CRL) { + gnutls_datum_t tmp; + + /* in that case encode it to a CertBag or + * a CrlBag. + */ + + result = + _pkcs12_encode_crt_bag(bag->element[i].type, + &bag->element[i].data, + &tmp); + + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + result = + _gnutls_x509_write_value(c2, "?LAST.bagValue", + &tmp); + + _gnutls_free_datum(&tmp); + + } else { + + result = + _gnutls_x509_write_value(c2, "?LAST.bagValue", + &bag->element[i]. + data); + } + + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + } + + /* Encode the data and copy them into the datum + */ + *contents = c2; + + return 0; + + cleanup: + if (c2) + asn1_delete_structure(&c2); + return result; } @@ -1342,45 +1278,49 @@ cleanup: * with the first certificate in chain (it is expected that chain_len==1) * and appends those in the chain. */ -static int make_chain(gnutls_x509_crt_t **chain, unsigned int *chain_len, - gnutls_x509_crt_t **extra_certs, unsigned int *extra_certs_len, - unsigned int flags) +static int make_chain(gnutls_x509_crt_t ** chain, unsigned int *chain_len, + gnutls_x509_crt_t ** extra_certs, + unsigned int *extra_certs_len, unsigned int flags) { -unsigned int i; - - if (*chain_len != 1) - return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - - i = 0; - while(i<*extra_certs_len) - { - /* if it is an issuer but not a self-signed one */ - if (gnutls_x509_crt_check_issuer((*chain)[*chain_len - 1], (*extra_certs)[i]) != 0) - { - if (!(flags & GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED) && - gnutls_x509_crt_check_issuer((*extra_certs)[i], (*extra_certs)[i]) != 0) - goto skip; - - *chain = gnutls_realloc_fast (*chain, sizeof((*chain)[0]) * - ++(*chain_len)); - if (*chain == NULL) - { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } - (*chain)[*chain_len - 1] = (*extra_certs)[i]; - - (*extra_certs)[i] = (*extra_certs)[*extra_certs_len-1]; - (*extra_certs_len)--; - - i=0; - continue; - } - -skip: - i++; - } - return 0; + unsigned int i; + + if (*chain_len != 1) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + i = 0; + while (i < *extra_certs_len) { + /* if it is an issuer but not a self-signed one */ + if (gnutls_x509_crt_check_issuer + ((*chain)[*chain_len - 1], (*extra_certs)[i]) != 0) { + if (!(flags & GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED) + && + gnutls_x509_crt_check_issuer((*extra_certs)[i], + (*extra_certs)[i]) + != 0) + goto skip; + + *chain = + gnutls_realloc_fast(*chain, + sizeof((*chain)[0]) * + ++(*chain_len)); + if (*chain == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + (*chain)[*chain_len - 1] = (*extra_certs)[i]; + + (*extra_certs)[i] = + (*extra_certs)[*extra_certs_len - 1]; + (*extra_certs_len)--; + + i = 0; + continue; + } + + skip: + i++; + } + return 0; } /** @@ -1433,413 +1373,385 @@ skip: * Since: 3.1 **/ int -gnutls_pkcs12_simple_parse (gnutls_pkcs12_t p12, - const char *password, - gnutls_x509_privkey_t * key, - gnutls_x509_crt_t ** chain, - unsigned int * chain_len, - gnutls_x509_crt_t ** extra_certs, - unsigned int * extra_certs_len, - gnutls_x509_crl_t * crl, - unsigned int flags) +gnutls_pkcs12_simple_parse(gnutls_pkcs12_t p12, + const char *password, + gnutls_x509_privkey_t * key, + gnutls_x509_crt_t ** chain, + unsigned int *chain_len, + gnutls_x509_crt_t ** extra_certs, + unsigned int *extra_certs_len, + gnutls_x509_crl_t * crl, unsigned int flags) { - gnutls_pkcs12_bag_t bag = NULL; - gnutls_x509_crt_t *_extra_certs = NULL; - unsigned int _extra_certs_len = 0; - gnutls_x509_crt_t *_chain = NULL; - unsigned int _chain_len = 0; - int idx = 0; - int ret; - size_t cert_id_size = 0; - size_t key_id_size = 0; - uint8_t cert_id[20]; - uint8_t key_id[20]; - int privkey_ok = 0; - unsigned int i; - - *key = NULL; - - if (crl) - *crl = NULL; - - /* find the first private key */ - for (;;) - { - int elements_in_bag; - int i; - - ret = gnutls_pkcs12_bag_init (&bag); - if (ret < 0) - { - bag = NULL; - gnutls_assert (); - goto done; - } - - ret = gnutls_pkcs12_get_bag (p12, idx, bag); - if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) - break; - if (ret < 0) - { - gnutls_assert (); - goto done; - } - - ret = gnutls_pkcs12_bag_get_type (bag, 0); - if (ret < 0) - { - gnutls_assert (); - goto done; - } - - if (ret == GNUTLS_BAG_ENCRYPTED) - { - if (password == NULL) - { - ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); - goto done; - } - - ret = gnutls_pkcs12_bag_decrypt (bag, password); - if (ret < 0) - { - gnutls_assert (); - goto done; - } - } - - elements_in_bag = gnutls_pkcs12_bag_get_count (bag); - if (elements_in_bag < 0) - { - gnutls_assert (); - goto done; - } - - for (i = 0; i < elements_in_bag; i++) - { - int type; - gnutls_datum_t data; - - type = gnutls_pkcs12_bag_get_type (bag, i); - if (type < 0) - { - gnutls_assert (); - goto done; - } - - ret = gnutls_pkcs12_bag_get_data (bag, i, &data); - if (ret < 0) - { - gnutls_assert (); - goto done; - } - - switch (type) - { - case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY: - if (password == NULL) - { - ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); - goto done; - } - - case GNUTLS_BAG_PKCS8_KEY: - if (*key != NULL) /* too simple to continue */ - { - gnutls_assert (); - break; - } - - ret = gnutls_x509_privkey_init (key); - if (ret < 0) - { - gnutls_assert (); - goto done; - } - - ret = gnutls_x509_privkey_import_pkcs8 - (*key, &data, GNUTLS_X509_FMT_DER, password, - type == GNUTLS_BAG_PKCS8_KEY ? GNUTLS_PKCS_PLAIN : 0); - if (ret < 0) - { - gnutls_assert (); - gnutls_x509_privkey_deinit (*key); - goto done; - } - - key_id_size = sizeof (key_id); - ret = - gnutls_x509_privkey_get_key_id (*key, 0, key_id, - &key_id_size); - if (ret < 0) - { - gnutls_assert (); - gnutls_x509_privkey_deinit (*key); - goto done; - } - - privkey_ok = 1; /* break */ - break; - default: - break; - } - } - - idx++; - gnutls_pkcs12_bag_deinit (bag); - - if (privkey_ok != 0) /* private key was found */ - break; - } - - if (privkey_ok == 0) /* no private key */ - { - gnutls_assert (); - return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; - } - - /* now find the corresponding certificate - */ - idx = 0; - bag = NULL; - for (;;) - { - int elements_in_bag; - int i; - - ret = gnutls_pkcs12_bag_init (&bag); - if (ret < 0) - { - bag = NULL; - gnutls_assert (); - goto done; - } - - ret = gnutls_pkcs12_get_bag (p12, idx, bag); - if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) - break; - if (ret < 0) - { - gnutls_assert (); - goto done; - } - - ret = gnutls_pkcs12_bag_get_type (bag, 0); - if (ret < 0) - { - gnutls_assert (); - goto done; - } - - if (ret == GNUTLS_BAG_ENCRYPTED) - { - ret = gnutls_pkcs12_bag_decrypt (bag, password); - if (ret < 0) - { - gnutls_assert (); - goto done; - } - } - - elements_in_bag = gnutls_pkcs12_bag_get_count (bag); - if (elements_in_bag < 0) - { - gnutls_assert (); - goto done; - } - - for (i = 0; i < elements_in_bag; i++) - { - int type; - gnutls_datum_t data; - gnutls_x509_crt_t this_cert; - - type = gnutls_pkcs12_bag_get_type (bag, i); - if (type < 0) - { - gnutls_assert (); - goto done; - } - - ret = gnutls_pkcs12_bag_get_data (bag, i, &data); - if (ret < 0) - { - gnutls_assert (); - goto done; - } - - switch (type) - { - case GNUTLS_BAG_CERTIFICATE: - ret = gnutls_x509_crt_init (&this_cert); - if (ret < 0) - { - gnutls_assert (); - goto done; - } - - ret = - gnutls_x509_crt_import (this_cert, &data, GNUTLS_X509_FMT_DER); - if (ret < 0) - { - gnutls_assert (); - gnutls_x509_crt_deinit (this_cert); - goto done; - } - - /* check if the key id match */ - cert_id_size = sizeof (cert_id); - ret = - gnutls_x509_crt_get_key_id (this_cert, 0, cert_id, &cert_id_size); - if (ret < 0) - { - gnutls_assert (); - gnutls_x509_crt_deinit (this_cert); - goto done; - } - - if (memcmp (cert_id, key_id, cert_id_size) != 0) - { /* they don't match - skip the certificate */ - if (extra_certs) - { - _extra_certs = gnutls_realloc_fast (_extra_certs, - sizeof(_extra_certs[0]) * - ++_extra_certs_len); - if (!_extra_certs) - { - gnutls_assert (); - ret = GNUTLS_E_MEMORY_ERROR; - goto done; - } - _extra_certs[_extra_certs_len - 1] = this_cert; - this_cert = NULL; - } - else - { - gnutls_x509_crt_deinit (this_cert); - } - } - else - { - if (chain && _chain_len == 0) - { - _chain = gnutls_malloc (sizeof(_chain[0]) * (++_chain_len)); - if (!_chain) - { - gnutls_assert (); - ret = GNUTLS_E_MEMORY_ERROR; - goto done; - } - _chain[_chain_len - 1] = this_cert; - this_cert = NULL; - } - else - { - gnutls_x509_crt_deinit (this_cert); - } - } - break; - - case GNUTLS_BAG_CRL: - if (crl == NULL || *crl != NULL) - { - gnutls_assert (); - break; - } - - ret = gnutls_x509_crl_init (crl); - if (ret < 0) - { - gnutls_assert (); - goto done; - } - - ret = gnutls_x509_crl_import (*crl, &data, GNUTLS_X509_FMT_DER); - if (ret < 0) - { - gnutls_assert (); - gnutls_x509_crl_deinit (*crl); - goto done; - } - break; - - case GNUTLS_BAG_ENCRYPTED: - /* XXX Bother to recurse one level down? Unlikely to - use the same password anyway. */ - case GNUTLS_BAG_EMPTY: - default: - break; - } - } - - idx++; - gnutls_pkcs12_bag_deinit (bag); - } - - if (chain != NULL) - { - if (_chain_len != 1) - { - ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; - goto done; - } - - ret = make_chain(&_chain, &_chain_len, &_extra_certs, &_extra_certs_len, flags); - if (ret < 0) - { - gnutls_assert(); - goto done; - } - } - - ret = 0; - -done: - if (bag) - gnutls_pkcs12_bag_deinit (bag); - - if (ret < 0) - { - if (*key) - gnutls_x509_privkey_deinit(*key); - if (_extra_certs_len && _extra_certs != NULL) - { - for (i = 0; i < _extra_certs_len; i++) - gnutls_x509_crt_deinit(_extra_certs[i]); - gnutls_free(_extra_certs); - } - if (_chain_len && _chain != NULL) - { - for (i = 0; i < _chain_len; i++) - gnutls_x509_crt_deinit(_chain[i]); - gnutls_free(_chain); - } - - return ret; - } - - if (extra_certs && _extra_certs_len > 0) - { - *extra_certs = _extra_certs; - *extra_certs_len = _extra_certs_len; - } - else - { - if (extra_certs) - { - *extra_certs = NULL; - *extra_certs_len = 0; - } - for (i = 0; i < _extra_certs_len; i++) - gnutls_x509_crt_deinit(_extra_certs[i]); - gnutls_free(_extra_certs); - } - - if (chain != NULL) - { - *chain = _chain; - *chain_len = _chain_len; - } - - return ret; + gnutls_pkcs12_bag_t bag = NULL; + gnutls_x509_crt_t *_extra_certs = NULL; + unsigned int _extra_certs_len = 0; + gnutls_x509_crt_t *_chain = NULL; + unsigned int _chain_len = 0; + int idx = 0; + int ret; + size_t cert_id_size = 0; + size_t key_id_size = 0; + uint8_t cert_id[20]; + uint8_t key_id[20]; + int privkey_ok = 0; + unsigned int i; + + *key = NULL; + + if (crl) + *crl = NULL; + + /* find the first private key */ + for (;;) { + int elements_in_bag; + int i; + + ret = gnutls_pkcs12_bag_init(&bag); + if (ret < 0) { + bag = NULL; + gnutls_assert(); + goto done; + } + + ret = gnutls_pkcs12_get_bag(p12, idx, bag); + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + break; + if (ret < 0) { + gnutls_assert(); + goto done; + } + + ret = gnutls_pkcs12_bag_get_type(bag, 0); + if (ret < 0) { + gnutls_assert(); + goto done; + } + + if (ret == GNUTLS_BAG_ENCRYPTED) { + if (password == NULL) { + ret = + gnutls_assert_val + (GNUTLS_E_DECRYPTION_FAILED); + goto done; + } + + ret = gnutls_pkcs12_bag_decrypt(bag, password); + if (ret < 0) { + gnutls_assert(); + goto done; + } + } + + elements_in_bag = gnutls_pkcs12_bag_get_count(bag); + if (elements_in_bag < 0) { + gnutls_assert(); + goto done; + } + + for (i = 0; i < elements_in_bag; i++) { + int type; + gnutls_datum_t data; + + type = gnutls_pkcs12_bag_get_type(bag, i); + if (type < 0) { + gnutls_assert(); + goto done; + } + + ret = gnutls_pkcs12_bag_get_data(bag, i, &data); + if (ret < 0) { + gnutls_assert(); + goto done; + } + + switch (type) { + case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY: + if (password == NULL) { + ret = + gnutls_assert_val + (GNUTLS_E_DECRYPTION_FAILED); + goto done; + } + + case GNUTLS_BAG_PKCS8_KEY: + if (*key != NULL) { /* too simple to continue */ + gnutls_assert(); + break; + } + + ret = gnutls_x509_privkey_init(key); + if (ret < 0) { + gnutls_assert(); + goto done; + } + + ret = gnutls_x509_privkey_import_pkcs8 + (*key, &data, GNUTLS_X509_FMT_DER, + password, + type == + GNUTLS_BAG_PKCS8_KEY ? + GNUTLS_PKCS_PLAIN : 0); + if (ret < 0) { + gnutls_assert(); + gnutls_x509_privkey_deinit(*key); + goto done; + } + + key_id_size = sizeof(key_id); + ret = + gnutls_x509_privkey_get_key_id(*key, 0, + key_id, + &key_id_size); + if (ret < 0) { + gnutls_assert(); + gnutls_x509_privkey_deinit(*key); + goto done; + } + + privkey_ok = 1; /* break */ + break; + default: + break; + } + } + + idx++; + gnutls_pkcs12_bag_deinit(bag); + + if (privkey_ok != 0) /* private key was found */ + break; + } + + if (privkey_ok == 0) { /* no private key */ + gnutls_assert(); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + /* now find the corresponding certificate + */ + idx = 0; + bag = NULL; + for (;;) { + int elements_in_bag; + int i; + + ret = gnutls_pkcs12_bag_init(&bag); + if (ret < 0) { + bag = NULL; + gnutls_assert(); + goto done; + } + + ret = gnutls_pkcs12_get_bag(p12, idx, bag); + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + break; + if (ret < 0) { + gnutls_assert(); + goto done; + } + + ret = gnutls_pkcs12_bag_get_type(bag, 0); + if (ret < 0) { + gnutls_assert(); + goto done; + } + + if (ret == GNUTLS_BAG_ENCRYPTED) { + ret = gnutls_pkcs12_bag_decrypt(bag, password); + if (ret < 0) { + gnutls_assert(); + goto done; + } + } + + elements_in_bag = gnutls_pkcs12_bag_get_count(bag); + if (elements_in_bag < 0) { + gnutls_assert(); + goto done; + } + + for (i = 0; i < elements_in_bag; i++) { + int type; + gnutls_datum_t data; + gnutls_x509_crt_t this_cert; + + type = gnutls_pkcs12_bag_get_type(bag, i); + if (type < 0) { + gnutls_assert(); + goto done; + } + + ret = gnutls_pkcs12_bag_get_data(bag, i, &data); + if (ret < 0) { + gnutls_assert(); + goto done; + } + + switch (type) { + case GNUTLS_BAG_CERTIFICATE: + ret = gnutls_x509_crt_init(&this_cert); + if (ret < 0) { + gnutls_assert(); + goto done; + } + + ret = + gnutls_x509_crt_import(this_cert, + &data, + GNUTLS_X509_FMT_DER); + if (ret < 0) { + gnutls_assert(); + gnutls_x509_crt_deinit(this_cert); + goto done; + } + + /* check if the key id match */ + cert_id_size = sizeof(cert_id); + ret = + gnutls_x509_crt_get_key_id(this_cert, + 0, cert_id, + &cert_id_size); + if (ret < 0) { + gnutls_assert(); + gnutls_x509_crt_deinit(this_cert); + goto done; + } + + if (memcmp(cert_id, key_id, cert_id_size) != 0) { /* they don't match - skip the certificate */ + if (extra_certs) { + _extra_certs = + gnutls_realloc_fast + (_extra_certs, + sizeof(_extra_certs + [0]) * + ++_extra_certs_len); + if (!_extra_certs) { + gnutls_assert(); + ret = + GNUTLS_E_MEMORY_ERROR; + goto done; + } + _extra_certs + [_extra_certs_len - + 1] = this_cert; + this_cert = NULL; + } else { + gnutls_x509_crt_deinit + (this_cert); + } + } else { + if (chain && _chain_len == 0) { + _chain = + gnutls_malloc(sizeof + (_chain + [0]) * + (++_chain_len)); + if (!_chain) { + gnutls_assert(); + ret = + GNUTLS_E_MEMORY_ERROR; + goto done; + } + _chain[_chain_len - 1] = + this_cert; + this_cert = NULL; + } else { + gnutls_x509_crt_deinit + (this_cert); + } + } + break; + + case GNUTLS_BAG_CRL: + if (crl == NULL || *crl != NULL) { + gnutls_assert(); + break; + } + + ret = gnutls_x509_crl_init(crl); + if (ret < 0) { + gnutls_assert(); + goto done; + } + + ret = + gnutls_x509_crl_import(*crl, &data, + GNUTLS_X509_FMT_DER); + if (ret < 0) { + gnutls_assert(); + gnutls_x509_crl_deinit(*crl); + goto done; + } + break; + + case GNUTLS_BAG_ENCRYPTED: + /* XXX Bother to recurse one level down? Unlikely to + use the same password anyway. */ + case GNUTLS_BAG_EMPTY: + default: + break; + } + } + + idx++; + gnutls_pkcs12_bag_deinit(bag); + } + + if (chain != NULL) { + if (_chain_len != 1) { + ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + goto done; + } + + ret = + make_chain(&_chain, &_chain_len, &_extra_certs, + &_extra_certs_len, flags); + if (ret < 0) { + gnutls_assert(); + goto done; + } + } + + ret = 0; + + done: + if (bag) + gnutls_pkcs12_bag_deinit(bag); + + if (ret < 0) { + if (*key) + gnutls_x509_privkey_deinit(*key); + if (_extra_certs_len && _extra_certs != NULL) { + for (i = 0; i < _extra_certs_len; i++) + gnutls_x509_crt_deinit(_extra_certs[i]); + gnutls_free(_extra_certs); + } + if (_chain_len && _chain != NULL) { + for (i = 0; i < _chain_len; i++) + gnutls_x509_crt_deinit(_chain[i]); + gnutls_free(_chain); + } + + return ret; + } + + if (extra_certs && _extra_certs_len > 0) { + *extra_certs = _extra_certs; + *extra_certs_len = _extra_certs_len; + } else { + if (extra_certs) { + *extra_certs = NULL; + *extra_certs_len = 0; + } + for (i = 0; i < _extra_certs_len; i++) + gnutls_x509_crt_deinit(_extra_certs[i]); + gnutls_free(_extra_certs); + } + + if (chain != NULL) { + *chain = _chain; + *chain_len = _chain_len; + } + + return ret; } |