/* Decodes an RSA privateKey from a PKCS8 structure. */ static int _decode_pkcs8_rsa_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey) { int ret; gnutls_datum_t tmp = {NULL, 0}; ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp); if (ret < 0) { gnutls_assert(); goto error; } pkey->key = _gnutls_privkey_decode_pkcs1_rsa_key(&tmp, pkey); _gnutls_free_key_datum(&tmp); if (pkey->key == NULL) { ret = GNUTLS_E_PK_INVALID_PRIVKEY; gnutls_assert(); goto error; } ret = 0; error: return ret; }
/** * gnutls_x509_crl_get_signature_algorithm - returns the CRL's signature algorithm * @crl: should contain a #gnutls_x509_crl_t structure * * This function will return a value of the #gnutls_sign_algorithm_t * enumeration that is the signature algorithm. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ int gnutls_x509_crl_get_signature_algorithm (gnutls_x509_crl_t crl) { int result; gnutls_datum_t sa; if (crl == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } /* Read the signature algorithm. Note that parameters are not * read. They will be read from the issuer's certificate if needed. */ result = _gnutls_x509_read_value (crl->crl, "signatureAlgorithm.algorithm", &sa, 0); if (result < 0) { gnutls_assert (); return result; } result = _gnutls_x509_oid2sign_algorithm ((const char *) sa.data); _gnutls_free_datum (&sa); return result; }
static int _parse_safe_contents (ASN1_TYPE sc, const char *sc_name, gnutls_pkcs12_bag_t bag) { gnutls_datum_t content = { NULL, 0 }; int result; /* Step 1. Extract the content. */ result = _gnutls_x509_read_value (sc, sc_name, &content, 1); 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); return 0; cleanup: _gnutls_free_datum (&content); return result; }
int _gnutls_decode_ber_rs_raw(const gnutls_datum_t * sig_value, gnutls_datum_t *r, gnutls_datum_t *s) { ASN1_TYPE sig; int result; if ((result = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.DSASignatureValue", &sig)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } result = asn1_der_decoding(&sig, sig_value->data, sig_value->size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); asn1_delete_structure(&sig); return _gnutls_asn2err(result); } result = _gnutls_x509_read_value(sig, "r", r); if (result < 0) { gnutls_assert(); asn1_delete_structure(&sig); return result; } result = _gnutls_x509_read_value(sig, "s", s); if (result < 0) { gnutls_assert(); gnutls_free(r->data); asn1_delete_structure(&sig); return result; } asn1_delete_structure(&sig); return 0; }
/* Decodes an X.509 Attribute (if multi==1) or an AttributeTypeAndValue * otherwise. * * octet_string should be non-zero if we are to decode octet strings after * decoding. * * The output is allocated and stored in value. */ int _gnutls_x509_decode_and_read_attribute(ASN1_TYPE asn1_struct, const char *where, char *oid, int oid_size, gnutls_datum_t * value, int multi, int octet_string) { char tmpbuffer[128]; int len, result; /* Read the OID */ _gnutls_str_cpy(tmpbuffer, sizeof(tmpbuffer), where); _gnutls_str_cat(tmpbuffer, sizeof(tmpbuffer), ".type"); len = oid_size - 1; result = asn1_read_value(asn1_struct, tmpbuffer, oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); return result; } /* Read the Value */ _gnutls_str_cpy(tmpbuffer, sizeof(tmpbuffer), where); _gnutls_str_cat(tmpbuffer, sizeof(tmpbuffer), ".value"); if (multi) _gnutls_str_cat(tmpbuffer, sizeof(tmpbuffer), "s.?1"); /* .values.?1 */ if (octet_string) result = _gnutls_x509_read_string(asn1_struct, tmpbuffer, value, ASN1_ETYPE_OCTET_STRING, 0); else result = _gnutls_x509_read_value(asn1_struct, tmpbuffer, value); if (result < 0) { gnutls_assert(); return result; } return 0; }
static int get_indx_extension(ASN1_TYPE asn, const char *root, int indx, gnutls_datum_t * out) { char name[ASN1_MAX_NAME_SIZE]; int ret; out->data = NULL; out->size = 0; snprintf(name, sizeof(name), "%s.?%u.extnValue", root, indx+1); ret = _gnutls_x509_read_value(asn, name, out); if (ret < 0) return gnutls_assert_val(ret); return 0; }
/* Decodes an ECC privateKey from a PKCS8 structure. */ static int _decode_pkcs8_ecc_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey) { int ret; gnutls_datum_t tmp = {NULL, 0}; unsigned char oid[MAX_OID_SIZE]; unsigned curve = GNUTLS_ECC_CURVE_INVALID; int len, result; /* openssl PKCS #8 files with ECC keys place the curve in * privateKeyAlgorithm.parameters instead of the ECPrivateKey.parameters. */ len = sizeof(oid); result = asn1_read_value(pkcs8_asn, "privateKeyAlgorithm.parameters", oid, &len); if (result == ASN1_SUCCESS) { ret = _gnutls_x509_read_ecc_params(oid, len, &curve); if (ret < 0) { _gnutls_debug_log("PKCS#8: unknown curve OID %s\n", oid); curve = GNUTLS_ECC_CURVE_INVALID; } } ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_privkey_decode_ecc_key(&pkey->key, &tmp, pkey, curve); _gnutls_free_key_datum(&tmp); if (ret < 0) { gnutls_assert(); goto error; } ret = 0; error: return ret; }
/* Decodes an RSA-PSS privateKey from a PKCS8 structure. */ static int _decode_pkcs8_rsa_pss_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey) { int ret; gnutls_datum_t tmp = {NULL, 0}; gnutls_x509_spki_st params; memset(¶ms, 0, sizeof(params)); ret = _gnutls_x509_read_value(pkcs8_asn, "privateKeyAlgorithm.parameters", &tmp); if (ret < 0) { if (ret == GNUTLS_E_ASN1_VALUE_NOT_FOUND || ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) goto skip_params; gnutls_assert(); goto error; } ret = _gnutls_x509_read_rsa_pss_params(tmp.data, tmp.size, ¶ms); _gnutls_free_key_datum(&tmp); if (ret < 0) { gnutls_assert(); goto error; } skip_params: ret = _decode_pkcs8_rsa_key(pkcs8_asn, pkey); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.algo = GNUTLS_PK_RSA_PSS; memcpy(&pkey->params.spki, ¶ms, sizeof(gnutls_x509_spki_st)); ret = 0; error: return ret; }
/*- * gnutls_x509_get_signature_algorithm: * @src: should contain an ASN1_TYPE structure * @src_name: the description of the signature field * * This function will return a value of the #gnutls_sign_algorithm_t * enumeration that is the signature algorithm that has been used to * sign this certificate. * * Returns: a #gnutls_sign_algorithm_t value, or a negative error code on * error. -*/ int _gnutls_x509_get_signature_algorithm(ASN1_TYPE src, const char *src_name) { int result; gnutls_datum_t sa; /* Read the signature algorithm. Note that parameters are not * read. They will be read from the issuer's certificate if needed. */ result = _gnutls_x509_read_value(src, src_name, &sa); if (result < 0) { gnutls_assert(); return result; } result = _gnutls_x509_oid2sign_algorithm((char *) sa.data); _gnutls_free_datum(&sa); return result; }
/* 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) { 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; int count = 0, i, attributes, j; size_t size; /* 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, 0); 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) { size = attr_val.size; result = _gnutls_x509_decode_octet_string (NULL, attr_val.data, size, attr_val.data, &size); attr_val.size = size; if (result < 0) { _gnutls_free_datum (&attr_val); gnutls_assert (); _gnutls_x509_log ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid); continue; } bag->element[i].local_key_id = attr_val; } else if (strcmp (oid, FRIENDLY_NAME_OID) == 0) { size = attr_val.size; result = _gnutls_x509_decode_octet_string ("BMPString", attr_val.data, size, attr_val.data, &size); attr_val.size = size; if (result < 0) { _gnutls_free_datum (&attr_val); gnutls_assert (); _gnutls_x509_log ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid); continue; } bag->element[i].friendly_name = ucs2_to_ascii (attr_val.data, attr_val.size); } else { _gnutls_free_datum (&attr_val); _gnutls_x509_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; }
/* Converts an ECC key to * an internal structure (gnutls_private_key) */ ASN1_TYPE _gnutls_privkey_decode_ecc_key (const gnutls_datum_t * raw_key, gnutls_x509_privkey_t pkey) { int ret; ASN1_TYPE pkey_asn; unsigned int version; char oid[MAX_OID_SIZE]; int oid_size; gnutls_datum out; gnutls_pk_params_init(&pkey->params); if ((ret = asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.ECPrivateKey", &pkey_asn)) != ASN1_SUCCESS) { gnutls_assert (); return NULL; } ret = asn1_der_decoding (&pkey_asn, raw_key->data, raw_key->size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert (); goto error; } ret = _gnutls_x509_read_uint (pkey_asn, "Version", &version); if (ret < 0) { gnutls_assert(); goto error; } if (version != 1) { _gnutls_debug_log("ECC private key version %u is not supported\n", version); gnutls_assert(); goto error; } /* read the curve */ oid_size = sizeof(oid); ret = asn1_read_value(pkey_asn, "parameters.namedCurve", oid, &oid_size); if (ret != ASN1_SUCCESS) { gnutls_assert (); goto error; } pkey->params.flags = _gnutls_oid_to_ecc_curve(oid); if (pkey->params.flags == GNUTLS_ECC_CURVE_INVALID) { _gnutls_debug_log("Curve %s is not supported\n", oid); gnutls_assert(); goto error; } ret = _gnutls_ecc_curve_fill_params(pkey->params.flags, &pkey->params); if (ret < 0) { gnutls_assert(); goto error; } /* read the public key */ ret = _gnutls_x509_read_value(pkey_asn, "publicKey", &out, 2); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_ecc_ansi_x963_import (out.data, out.size, &pkey->params.params[ECC_X], &pkey->params.params[ECC_Y]); _gnutls_free_datum(&out); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.params_nr += 2; /* read the private key */ ret = _gnutls_x509_read_int (pkey_asn, "privateKey", &pkey->params.params[ECC_K]); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.params_nr ++; return pkey_asn; error: asn1_delete_structure (&pkey_asn); gnutls_pk_params_release (&pkey->params); return NULL; }
/** * gnutls_pkcs12_mac_info: * @pkcs12: A pkcs12 type * @mac: the MAC algorithm used as %gnutls_mac_algorithm_t * @salt: the salt used for string to key (if non-NULL then @salt_size initially holds its size) * @salt_size: string to key salt size * @iter_count: string to key iteration count * @oid: if non-NULL it will contain an allocated null-terminated variable with the OID * * This function will provide information on the MAC algorithm used * in a PKCS #12 structure. If the structure algorithms * are unknown the code %GNUTLS_E_UNKNOWN_HASH_ALGORITHM will be returned, * and only @oid, will be set. That is, @oid will be set on structures * with a MAC whether supported or not. It must be deinitialized using gnutls_free(). * The other variables are only set on supported structures. * * Returns: %GNUTLS_E_INVALID_REQUEST if the provided structure doesn't contain a MAC, * %GNUTLS_E_UNKNOWN_HASH_ALGORITHM if the structure's MAC isn't supported, or * another negative error code in case of a failure. Zero on success. **/ int gnutls_pkcs12_mac_info(gnutls_pkcs12_t pkcs12, unsigned int *mac, void *salt, unsigned int *salt_size, unsigned int *iter_count, char **oid) { int ret; gnutls_datum_t tmp = { NULL, 0 }, dsalt = { NULL, 0}; gnutls_mac_algorithm_t algo; if (oid) *oid = NULL; if (pkcs12 == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_x509_read_value(pkcs12->pkcs12, "macData.mac.digestAlgorithm.algorithm", &tmp); if (ret < 0) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } if (oid) { *oid = (char*)tmp.data; } algo = gnutls_oid_to_digest((char*)tmp.data); if (algo == GNUTLS_MAC_UNKNOWN || mac_to_entry(algo) == NULL) { gnutls_assert(); return GNUTLS_E_UNKNOWN_HASH_ALGORITHM; } if (oid) { tmp.data = NULL; } if (mac) { *mac = algo; } if (iter_count) { ret = _gnutls_x509_read_uint(pkcs12->pkcs12, "macData.iterations", iter_count); if (ret < 0) { *iter_count = 1; /* the default */ } } if (salt) { /* Read the salt from the structure. */ ret = _gnutls_x509_read_null_value(pkcs12->pkcs12, "macData.macSalt", &dsalt); if (ret < 0) { gnutls_assert(); goto cleanup; } if (*salt_size >= (unsigned)dsalt.size) { *salt_size = dsalt.size; if (dsalt.size > 0) memcpy(salt, dsalt.data, dsalt.size); } else { *salt_size = dsalt.size; ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); goto cleanup; } } ret = 0; cleanup: _gnutls_free_datum(&tmp); _gnutls_free_datum(&dsalt); return ret; }
/* Extracts DSA and RSA parameters from a certificate. */ static int get_mpis (int pk_algorithm, ASN1_TYPE asn, const char *root, bigint_t * params, int *params_size) { int result; char name[256]; gnutls_datum tmp = { NULL, 0 }; /* Read the algorithm's parameters */ snprintf (name, sizeof (name), "%s.subjectPublicKey", root); result = _gnutls_x509_read_value (asn, name, &tmp, 2); if (result < 0) { gnutls_assert (); fprintf (stderr, "name: %s\n", name); return result; } switch (pk_algorithm) { case GNUTLS_PK_RSA: /* params[0] is the modulus, * params[1] is the exponent */ if (*params_size < RSA_PUBLIC_PARAMS) { gnutls_assert (); /* internal error. Increase the bigint_ts in params */ result = GNUTLS_E_INTERNAL_ERROR; goto error; } if ((result = _gnutls_x509_read_rsa_params (tmp.data, tmp.size, params)) < 0) { gnutls_assert (); goto error; } *params_size = RSA_PUBLIC_PARAMS; break; case GNUTLS_PK_DSA: /* params[0] is p, * params[1] is q, * params[2] is q, * params[3] is pub. */ if (*params_size < DSA_PUBLIC_PARAMS) { gnutls_assert (); /* internal error. Increase the bigint_ts in params */ result = GNUTLS_E_INTERNAL_ERROR; goto error; } if ((result = _gnutls_x509_read_dsa_pubkey (tmp.data, tmp.size, params)) < 0) { gnutls_assert (); goto error; } /* Now read the parameters */ _gnutls_free_datum (&tmp); snprintf (name, sizeof (name), "%s.algorithm.parameters", root); result = _gnutls_x509_read_value (asn, name, &tmp, 0); /* FIXME: If the parameters are not included in the certificate * then the issuer's parameters should be used. This is not * done yet. */ if (result < 0) { gnutls_assert (); goto error; } if ((result = _gnutls_x509_read_dsa_params (tmp.data, tmp.size, params)) < 0) { gnutls_assert (); goto error; } *params_size = DSA_PUBLIC_PARAMS; break; default: /* other types like DH * currently not supported */ gnutls_assert (); result = GNUTLS_E_X509_CERTIFICATE_ERROR; goto error; } result = 0; error: _gnutls_free_datum (&tmp); return result; }
/* Extracts DSA and RSA parameters from a certificate. */ int _gnutls_x509_crt_get_mpis (gnutls_x509_crt_t cert, bigint_t * params, int *params_size) { int result; int pk_algorithm; gnutls_datum tmp = { NULL, 0 }; /* Read the algorithm's OID */ pk_algorithm = gnutls_x509_crt_get_pk_algorithm (cert, NULL); /* Read the algorithm's parameters */ result = _gnutls_x509_read_value (cert->cert, "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey", &tmp, 2); if (result < 0) { gnutls_assert (); return result; } switch (pk_algorithm) { case GNUTLS_PK_RSA: /* params[0] is the modulus, * params[1] is the exponent */ if (*params_size < RSA_PUBLIC_PARAMS) { gnutls_assert (); /* internal error. Increase the bigint_ts in params */ result = GNUTLS_E_INTERNAL_ERROR; goto error; } if ((result = _gnutls_x509_read_rsa_params (tmp.data, tmp.size, params)) < 0) { gnutls_assert (); goto error; } *params_size = RSA_PUBLIC_PARAMS; break; case GNUTLS_PK_DSA: /* params[0] is p, * params[1] is q, * params[2] is q, * params[3] is pub. */ if (*params_size < DSA_PUBLIC_PARAMS) { gnutls_assert (); /* internal error. Increase the bigint_ts in params */ result = GNUTLS_E_INTERNAL_ERROR; goto error; } if ((result = _gnutls_x509_read_dsa_pubkey (tmp.data, tmp.size, params)) < 0) { gnutls_assert (); goto error; } /* Now read the parameters */ _gnutls_free_datum (&tmp); result = _gnutls_x509_read_value (cert->cert, "tbsCertificate.subjectPublicKeyInfo.algorithm.parameters", &tmp, 0); /* FIXME: If the parameters are not included in the certificate * then the issuer's parameters should be used. This is not * done yet. */ if (result < 0) { gnutls_assert (); goto error; } if ((result = _gnutls_x509_read_dsa_params (tmp.data, tmp.size, params)) < 0) { gnutls_assert (); goto error; } *params_size = DSA_PUBLIC_PARAMS; break; default: /* other types like DH * currently not supported */ gnutls_assert (); result = GNUTLS_E_X509_CERTIFICATE_ERROR; goto error; } result = 0; error: _gnutls_free_datum (&tmp); return result; }
static int append_elements(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, gnutls_buffer_st *str, int k1, unsigned last) { int k2, result, max_k2; int len; uint8_t value[MAX_STRING_LEN]; char tmpbuffer1[ASN1_MAX_NAME_SIZE]; char tmpbuffer2[ASN1_MAX_NAME_SIZE]; char tmpbuffer3[ASN1_MAX_NAME_SIZE]; const char *ldap_desc; char oid[MAX_OID_SIZE]; gnutls_datum_t td = { NULL, 0 }; gnutls_datum_t tvd = { NULL, 0 }; /* create a string like "tbsCertList.issuer.rdnSequence.?1" */ if (asn1_rdn_name[0] != 0) snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u", asn1_rdn_name, k1); else snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u", k1); len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len); if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */ gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } k2 = 0; result = asn1_number_of_elements(asn1_struct, tmpbuffer1, &max_k2); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } do { /* Move to the attibute type and values */ k2++; if (tmpbuffer1[0] != 0) snprintf(tmpbuffer2, sizeof(tmpbuffer2), "%s.?%u", tmpbuffer1, k2); else snprintf(tmpbuffer2, sizeof(tmpbuffer2), "?%u", k2); /* Try to read the RelativeDistinguishedName attributes. */ len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer2, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) { /* expected */ gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the OID */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type"); len = sizeof(oid) - 1; result = asn1_read_value(asn1_struct, tmpbuffer3, oid, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; else if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the Value */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".value"); len = 0; result = _gnutls_x509_read_value(asn1_struct, tmpbuffer3, &tvd); if (result < 0) { gnutls_assert(); goto cleanup; } #define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( str, y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } #define DATA_APPEND(x,y) if ((result=_gnutls_buffer_append_data( str, x,y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } /* The encodings of adjoining RelativeDistinguishedNames are separated * by a comma character (',' ASCII 44). */ ldap_desc = gnutls_x509_dn_oid_name(oid, GNUTLS_X509_DN_OID_RETURN_OID); STR_APPEND(ldap_desc); STR_APPEND("="); result = _gnutls_x509_dn_to_string(oid, tvd.data, tvd.size, &td); if (result < 0) { gnutls_assert(); _gnutls_debug_log ("Cannot parse OID: '%s' with value '%s'\n", oid, _gnutls_bin2hex(tvd.data, tvd.size, tmpbuffer3, sizeof (tmpbuffer3), NULL)); goto cleanup; } DATA_APPEND(td.data, td.size); _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); /* Where there is a multi-valued RDN, the outputs from adjoining * AttributeTypeAndValues are separated by a plus ('+' ASCII 43) * character. */ if (k2 < max_k2) { STR_APPEND("+"); } else if (!last) { STR_APPEND(","); } } while (1); result = 0; cleanup: _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); return result; }
/* Parses an X509 DN in the asn1_struct, and searches for the * given OID in the DN. * * If raw_flag == 0, the output will be encoded in the LDAP way. (#hex for non printable) * Otherwise the raw DER data are returned. * * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence". * That is to point in the rndSequence. * * indx specifies which OID to return. Ie 0 means return the first specified * OID found, 1 the second etc. */ int _gnutls_x509_parse_dn_oid(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, const char *given_oid, int indx, unsigned int raw_flag, gnutls_datum_t * out) { int k2, k1, result; char tmpbuffer1[ASN1_MAX_NAME_SIZE]; char tmpbuffer2[ASN1_MAX_NAME_SIZE]; char tmpbuffer3[ASN1_MAX_NAME_SIZE]; gnutls_datum_t td; uint8_t value[256]; char oid[MAX_OID_SIZE]; int len; int i = 0; k1 = 0; do { k1++; /* create a string like "tbsCertList.issuer.rdnSequence.?1" */ if (asn1_rdn_name[0] != 0) snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u", asn1_rdn_name, k1); else snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u", k1); len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { gnutls_assert(); break; } if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } k2 = 0; do { /* Move to the attibute type and values */ k2++; if (tmpbuffer1[0] != 0) snprintf(tmpbuffer2, sizeof(tmpbuffer2), "%s.?%u", tmpbuffer1, k2); else snprintf(tmpbuffer2, sizeof(tmpbuffer2), "?%u", k2); /* Try to read the RelativeDistinguishedName attributes. */ len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer2, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { break; } if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the OID */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type"); len = sizeof(oid) - 1; result = asn1_read_value(asn1_struct, tmpbuffer3, oid, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; else if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (strcmp(oid, given_oid) == 0 && indx == i++) { /* Found the OID */ /* Read the Value */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".value"); result = _gnutls_x509_read_value(asn1_struct, tmpbuffer3, &td); if (result < 0) { gnutls_assert(); goto cleanup; } if (raw_flag != 0) { out->data = td.data; out->size = td.size; return 0; } else { /* parse data. raw_flag == 0 */ result = _gnutls_x509_dn_to_string(oid, td. data, td. size, out); _gnutls_free_datum(&td); if (result < 0) { gnutls_assert(); goto cleanup; } return 0; } /* raw_flag == 0 */ } } while (1); } while (1); gnutls_assert(); result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; cleanup: return result; }
/* extract the proxyCertInfo from the DER encoded extension */ int _gnutls_x509_ext_extract_proxyCertInfo (int *pathLenConstraint, char **policyLanguage, char **policy, size_t * sizeof_policy, uint8_t * extnValue, int extnValueLen) { ASN1_TYPE ext = ASN1_TYPE_EMPTY; int result; gnutls_datum_t value; if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.ProxyCertInfo", &ext)) != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } result = asn1_der_decoding (&ext, extnValue, extnValueLen, NULL); if (result != ASN1_SUCCESS) { gnutls_assert (); asn1_delete_structure (&ext); return _gnutls_asn2err (result); } if (pathLenConstraint) { result = _gnutls_x509_read_uint (ext, "pCPathLenConstraint", (unsigned int*)pathLenConstraint); if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) *pathLenConstraint = -1; else if (result != GNUTLS_E_SUCCESS) { asn1_delete_structure (&ext); return _gnutls_asn2err (result); } } result = _gnutls_x509_read_value (ext, "proxyPolicy.policyLanguage", &value); if (result < 0) { gnutls_assert (); asn1_delete_structure (&ext); return result; } if (policyLanguage) *policyLanguage = gnutls_strdup ((char*)value.data); result = _gnutls_x509_read_value (ext, "proxyPolicy.policy", &value); if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) { if (policy) *policy = NULL; if (sizeof_policy) *sizeof_policy = 0; } else if (result < 0) { gnutls_assert (); asn1_delete_structure (&ext); return result; } else { if (policy) *policy = (char*)value.data; if (sizeof_policy) *sizeof_policy = value.size; } asn1_delete_structure (&ext); return 0; }
static int decode_complex_string(const struct oid_to_string *oentry, void *value, int value_size, gnutls_datum_t * out) { char str[MAX_STRING_LEN], tmpname[128]; int len = -1, result; ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY; char asn1_err[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = ""; unsigned int etype; gnutls_datum_t td = {NULL, 0}; if (oentry->asn_desc == NULL) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } if ((result = asn1_create_element(_gnutls_get_pkix(), oentry->asn_desc, &tmpasn)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } if ((result = asn1_der_decoding(&tmpasn, value, value_size, asn1_err)) != ASN1_SUCCESS) { gnutls_assert(); _gnutls_debug_log("asn1_der_decoding: %s\n", asn1_err); asn1_delete_structure(&tmpasn); return _gnutls_asn2err(result); } /* Read the type of choice. */ len = sizeof(str) - 1; if ((result = asn1_read_value(tmpasn, "", str, &len)) != ASN1_SUCCESS) { /* CHOICE */ gnutls_assert(); asn1_delete_structure(&tmpasn); return _gnutls_asn2err(result); } str[len] = 0; /* We set the etype on the strings that may need * some conversion to UTF-8. The INVALID flag indicates * no conversion needed */ if (strcmp(str, "teletexString") == 0) etype = ASN1_ETYPE_TELETEX_STRING; else if (strcmp(str, "bmpString") == 0) etype = ASN1_ETYPE_BMP_STRING; else if (strcmp(str, "universalString") == 0) etype = ASN1_ETYPE_UNIVERSAL_STRING; else etype = ASN1_ETYPE_INVALID; _gnutls_str_cpy(tmpname, sizeof(tmpname), str); result = _gnutls_x509_read_value(tmpasn, tmpname, &td); asn1_delete_structure(&tmpasn); if (result < 0) return gnutls_assert_val(result); if (etype != ASN1_ETYPE_INVALID) { result = make_printable_string(etype, &td, out); _gnutls_free_datum(&td); if (result < 0) return gnutls_assert_val(result); } else { out->data = td.data; out->size = td.size; /* _gnutls_x509_read_value always null terminates */ } /* Refuse to deal with strings containing NULs. */ if (strlen((void *) out->data) != (size_t) out->size) { _gnutls_free_datum(out); return gnutls_assert_val(GNUTLS_E_ASN1_DER_ERROR); } return 0; }
int _pkcs12_decode_crt_bag (gnutls_pkcs12_bag_type_t type, const gnutls_datum_t * in, gnutls_datum_t * out) { int ret; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; if (type == GNUTLS_BAG_CERTIFICATE) { if ((ret = asn1_create_element (_gnutls_get_pkix (), "PKIX1.pkcs-12-CertBag", &c2)) != ASN1_SUCCESS) { gnutls_assert (); ret = _gnutls_asn2err (ret); goto cleanup; } ret = asn1_der_decoding (&c2, in->data, in->size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert (); ret = _gnutls_asn2err (ret); goto cleanup; } ret = _gnutls_x509_read_value (c2, "certValue", out, 1); if (ret < 0) { gnutls_assert (); goto cleanup; } } else { /* CRL */ if ((ret = asn1_create_element (_gnutls_get_pkix (), "PKIX1.pkcs-12-CRLBag", &c2)) != ASN1_SUCCESS) { gnutls_assert (); ret = _gnutls_asn2err (ret); goto cleanup; } ret = asn1_der_decoding (&c2, in->data, in->size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert (); ret = _gnutls_asn2err (ret); goto cleanup; } ret = _gnutls_x509_read_value (c2, "crlValue", out, 1); if (ret < 0) { gnutls_assert (); goto cleanup; } } asn1_delete_structure (&c2); return 0; cleanup: asn1_delete_structure (&c2); return ret; }
/** * gnutls_pkcs12_get_bag: * @pkcs12: should contain a gnutls_pkcs12_t structure * @indx: contains the index of the bag to extract * @bag: An initialized bag, where the contents of the bag will be copied * * This function will return a Bag from the PKCS12 structure. * * After the last Bag has been read * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ int 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, 0); if (result < 0) { gnutls_assert (); goto cleanup; } result = 0; cleanup: if (c2) asn1_delete_structure (&c2); return result; }
static int principal_to_str(ASN1_TYPE c2, gnutls_buffer_st * str) { gnutls_datum_t realm = { NULL, 0 }; gnutls_datum_t component = { NULL, 0 }; unsigned char name_type[2]; int ret, result, len; unsigned i; char val[128]; ret = _gnutls_x509_read_value(c2, "realm", &realm); if (ret < 0) { gnutls_assert(); return ret; } len = sizeof(name_type); result = asn1_read_value(c2, "principalName.name-type", name_type, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } if (len != 1 || (name_type[0] != 1 && name_type[0] != 2 && name_type[0] != 10)) { ret = GNUTLS_E_INVALID_REQUEST; goto cleanup; } for (i = 0;; i++) { snprintf(val, sizeof(val), "principalName.name-string.?%u", i + 1); ret = _gnutls_x509_read_value(c2, val, &component); if (ret == GNUTLS_E_ASN1_VALUE_NOT_FOUND || ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) break; if (ret < 0) { gnutls_assert(); goto cleanup; } if (i > 0) { ret = _gnutls_buffer_append_data(str, "/", 1); if (ret < 0) { gnutls_assert(); goto cleanup; } } ret = _gnutls_buffer_append_data(str, component.data, component.size); if (ret < 0) { gnutls_assert(); goto cleanup; } _gnutls_free_datum(&component); } ret = _gnutls_buffer_append_data(str, "@", 1); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_buffer_append_data(str, realm.data, realm.size); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = 0; cleanup: _gnutls_free_datum(&component); gnutls_free(realm.data); return ret; }
/* Decodes an DSA privateKey and params from a PKCS8 structure. */ static int _decode_pkcs8_dsa_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey) { int ret; gnutls_datum_t tmp = {NULL, 0}; gnutls_pk_params_init(&pkey->params); ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_x509_read_der_int(tmp.data, tmp.size, &pkey->params.params[4]); _gnutls_free_key_datum(&tmp); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_x509_read_value(pkcs8_asn, "privateKeyAlgorithm.parameters", &tmp); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_x509_read_pubkey_params(GNUTLS_PK_DSA, tmp.data, tmp.size, &pkey->params); _gnutls_free_datum(&tmp); if (ret < 0) { gnutls_assert(); goto error; } if (_gnutls_mpi_cmp_ui(pkey->params.params[0], 0) == 0) { gnutls_assert(); ret = GNUTLS_E_ILLEGAL_PARAMETER; goto error; } /* the public key can be generated as g^x mod p */ ret = _gnutls_mpi_init(&pkey->params.params[3]); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_mpi_powm(pkey->params.params[3], pkey->params.params[2], pkey->params.params[4], pkey->params.params[0]); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.algo = GNUTLS_PK_DSA; pkey->params.params_nr = DSA_PRIVATE_PARAMS; ret = _gnutls_asn1_encode_privkey(&pkey->key, &pkey->params); if (ret < 0) { gnutls_assert(); goto error; } return 0; error: if (pkey->params.params_nr != DSA_PRIVATE_PARAMS) _gnutls_mpi_release(&pkey->params.params[4]); return ret; }
/* Decodes a GOST privateKey from a PKCS8 structure. */ static int _decode_pkcs8_gost_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey, gnutls_pk_algorithm_t algo) { int ret; gnutls_datum_t tmp; unsigned char oid[3 * MAX_OID_SIZE]; /* GOST parameters can have 3 OIDs at most */ int len, result; gnutls_pk_params_init(&pkey->params); len = sizeof(oid); result = asn1_read_value(pkcs8_asn, "privateKeyAlgorithm.parameters", oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = GNUTLS_E_PARSING_ERROR; goto error; } else { ret = _gnutls_x509_read_gost_params(oid, len, &pkey->params, algo); if (ret < 0) { gnutls_assert(); goto error; } } /* Will be fixed later by pk_fixup */ ret = _gnutls_mpi_init(&pkey->params.params[GOST_X]); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.params_nr++; ret = _gnutls_mpi_init(&pkey->params.params[GOST_Y]); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.params_nr++; _gnutls_mpi_set_ui(pkey->params.params[GOST_X], 0); _gnutls_mpi_set_ui(pkey->params.params[GOST_Y], 0); ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp); if (ret < 0) { gnutls_assert(); goto error; } ret = _privkey_decode_gost_key(&tmp, pkey); _gnutls_free_key_datum(&tmp); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.algo = algo; return 0; error: gnutls_pk_params_clear(&pkey->params); gnutls_pk_params_release(&pkey->params); return ret; }
/* Decodes the PKCS #12 auth_safe, and returns the allocated raw data, * 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) { 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_x509_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_value (pkcs12, "authSafe.content", &auth_safe, 1); 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_x509_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; }
int get_extension (ASN1_TYPE asn, const char *root, const char *extension_id, int indx, gnutls_datum_t * ret, unsigned int *_critical) { int k, result, len; char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE]; char str[1024]; char str_critical[10]; int critical = 0; char extnID[128]; gnutls_datum_t value; int indx_counter = 0; ret->data = NULL; ret->size = 0; k = 0; do { k++; snprintf (name, sizeof (name), "%s.?%u", root, k); len = sizeof (str) - 1; result = asn1_read_value (asn, name, str, &len); /* move to next */ if (result == ASN1_ELEMENT_NOT_FOUND) { break; } do { _gnutls_str_cpy (name2, sizeof (name2), name); _gnutls_str_cat (name2, sizeof (name2), ".extnID"); len = sizeof (extnID) - 1; result = asn1_read_value (asn, name2, extnID, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { gnutls_assert (); break; } else if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } /* Handle Extension */ if (strcmp (extnID, extension_id) == 0 && indx == indx_counter++) { /* extension was found */ /* read the critical status. */ _gnutls_str_cpy (name2, sizeof (name2), name); _gnutls_str_cat (name2, sizeof (name2), ".critical"); len = sizeof (str_critical); result = asn1_read_value (asn, name2, str_critical, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { gnutls_assert (); break; } else if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } if (str_critical[0] == 'T') critical = 1; else critical = 0; /* read the value. */ _gnutls_str_cpy (name2, sizeof (name2), name); _gnutls_str_cat (name2, sizeof (name2), ".extnValue"); result = _gnutls_x509_read_value (asn, name2, &value); if (result < 0) { gnutls_assert (); return result; } ret->data = value.data; ret->size = value.size; if (_critical) *_critical = critical; return 0; } } while (0); } while (1); if (result == ASN1_ELEMENT_NOT_FOUND) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } else { gnutls_assert (); return _gnutls_asn2err (result); } }
int _gnutls_x509_get_dn(ASN1_TYPE asn1_struct, const char *asn1_rdn_name, gnutls_datum_t * dn) { gnutls_buffer_st out_str; int k2, k1, result; char tmpbuffer1[ASN1_MAX_NAME_SIZE]; char tmpbuffer2[ASN1_MAX_NAME_SIZE]; char tmpbuffer3[ASN1_MAX_NAME_SIZE]; uint8_t value[MAX_STRING_LEN]; gnutls_datum_t td = { NULL, 0 }, tvd = { NULL, 0}; const char *ldap_desc; char oid[MAX_OID_SIZE]; int len; _gnutls_buffer_init(&out_str); k1 = 0; do { k1++; /* create a string like "tbsCertList.issuer.rdnSequence.?1" */ if (asn1_rdn_name[0] != 0) snprintf(tmpbuffer1, sizeof(tmpbuffer1), "%s.?%u", asn1_rdn_name, k1); else snprintf(tmpbuffer1, sizeof(tmpbuffer1), "?%u", k1); len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer1, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) { if (k1 == 1) { gnutls_assert(); result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto cleanup; } break; } if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } k2 = 0; do { /* Move to the attibute type and values */ k2++; if (tmpbuffer1[0] != 0) snprintf(tmpbuffer2, sizeof(tmpbuffer2), "%s.?%u", tmpbuffer1, k2); else snprintf(tmpbuffer2, sizeof(tmpbuffer2), "?%u", k2); /* Try to read the RelativeDistinguishedName attributes. */ len = sizeof(value) - 1; result = asn1_read_value(asn1_struct, tmpbuffer2, value, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; if (result != ASN1_VALUE_NOT_FOUND) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the OID */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".type"); len = sizeof(oid) - 1; result = asn1_read_value(asn1_struct, tmpbuffer3, oid, &len); if (result == ASN1_ELEMENT_NOT_FOUND) break; else if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } /* Read the Value */ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3), tmpbuffer2); _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3), ".value"); len = 0; result = _gnutls_x509_read_value(asn1_struct, tmpbuffer3, &tvd); if (result < 0) { gnutls_assert(); goto cleanup; } #define STR_APPEND(y) if ((result=_gnutls_buffer_append_str( &out_str, y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } #define DATA_APPEND(x,y) if ((result=_gnutls_buffer_append_data( &out_str, x,y)) < 0) { \ gnutls_assert(); \ goto cleanup; \ } /* The encodings of adjoining RelativeDistinguishedNames are separated * by a comma character (',' ASCII 44). */ /* Where there is a multi-valued RDN, the outputs from adjoining * AttributeTypeAndValues are separated by a plus ('+' ASCII 43) * character. */ if (k1 != 1) { /* the first time do not append a comma */ if (k2 != 1) { /* adjoining multi-value RDN */ STR_APPEND("+"); } else { STR_APPEND(","); } } ldap_desc = gnutls_x509_dn_oid_name(oid, GNUTLS_X509_DN_OID_RETURN_OID); STR_APPEND(ldap_desc); STR_APPEND("="); result = _gnutls_x509_dn_to_string(oid, tvd.data, tvd.size, &td); if (result < 0) { gnutls_assert(); _gnutls_debug_log ("Cannot parse OID: '%s' with value '%s'\n", oid, _gnutls_bin2hex(tvd.data, tvd.size, tmpbuffer3, sizeof (tmpbuffer3), NULL)); goto cleanup; } DATA_APPEND(td.data, td.size); _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); } while (1); } while (1); result = _gnutls_buffer_to_datum(&out_str, dn, 1); if (result < 0) gnutls_assert(); goto cleanup1; cleanup: _gnutls_buffer_clear(&out_str); cleanup1: _gnutls_free_datum(&td); _gnutls_free_datum(&tvd); return result; }
/** * gnutls_pkcs12_verify_mac: * @pkcs12: should contain a gnutls_pkcs12_t structure * @pass: The password for the MAC * * This function will verify the MAC for the PKCS12 structure. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ int gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass) { opaque key[20]; int result; unsigned int iter; int len; digest_hd_st td1; gnutls_datum_t tmp = { NULL, 0 }, salt = { NULL, 0}; opaque sha_mac[20]; opaque 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, 0); 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_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key)); if (result < 0) { gnutls_assert (); goto cleanup; } _gnutls_hmac (&td1, tmp.data, tmp.size); _gnutls_free_datum (&tmp); _gnutls_hmac_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; }
/* Converts an ECC key to * an internal structure (gnutls_private_key) */ int _gnutls_privkey_decode_ecc_key(ASN1_TYPE* pkey_asn, const gnutls_datum_t * raw_key, gnutls_x509_privkey_t pkey, gnutls_ecc_curve_t curve) { int ret; unsigned int version; char oid[MAX_OID_SIZE]; int oid_size; gnutls_datum out; gnutls_pk_params_init(&pkey->params); pkey->params.algo = GNUTLS_PK_EC; if ((ret = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.ECPrivateKey", pkey_asn)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(ret); } ret = asn1_der_decoding(pkey_asn, raw_key->data, raw_key->size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto error; } ret = _gnutls_x509_read_uint(*pkey_asn, "Version", &version); if (ret < 0) { gnutls_assert(); goto error; } if (version != 1) { _gnutls_debug_log ("ECC private key version %u is not supported\n", version); gnutls_assert(); ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE; goto error; } /* read the curve */ if (curve == GNUTLS_ECC_CURVE_INVALID) { oid_size = sizeof(oid); ret = asn1_read_value(*pkey_asn, "parameters.namedCurve", oid, &oid_size); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto error; } pkey->params.flags = _gnutls_oid_to_ecc_curve(oid); if (pkey->params.flags == GNUTLS_ECC_CURVE_INVALID) { _gnutls_debug_log("Curve %s is not supported\n", oid); gnutls_assert(); ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE; goto error; } } else { pkey->params.flags = curve; } /* read the public key */ ret = _gnutls_x509_read_value(*pkey_asn, "publicKey", &out); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_ecc_ansi_x963_import(out.data, out.size, &pkey->params.params[ECC_X], &pkey->params.params[ECC_Y]); _gnutls_free_datum(&out); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.params_nr += 2; /* read the private key */ ret = _gnutls_x509_read_key_int(*pkey_asn, "privateKey", &pkey->params.params[ECC_K]); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.params_nr++; return 0; error: asn1_delete_structure2(pkey_asn, ASN1_DELETE_FLAG_ZEROIZE); gnutls_pk_params_clear(&pkey->params); gnutls_pk_params_release(&pkey->params); return ret; }