static void get_certificate (ASN1_TYPE cert_def, unsigned char *der, int der_len) { int result, len, start, end; unsigned char str[1024], str2[1024]; ASN1_TYPE cert2 = ASN1_TYPE_EMPTY; char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; asn1_create_element (cert_def, "PKIX1Implicit88.Certificate", &cert2); result = asn1_der_decoding (&cert2, der, der_len, errorDescription); if (result != ASN1_SUCCESS) { printf ("Problems with DER encoding\n"); return; } /* issuer */ get_Name_type (cert_def, cert2, "tbsCertificate.issuer", str); printf ("certificate:\nissuer :%s\n", str); /* subject */ get_Name_type (cert_def, cert2, "tbsCertificate.subject", str); printf ("subject:%s\n", str); /* Verify sign */ len = sizeof (str) - 1; result = asn1_read_value (cert2, "signatureAlgorithm.algorithm", str, &len); len = sizeof (str2) - 1; result = asn1_read_value (cert_def, "PKIX1Implicit88.id-dsa-with-sha1", str2, &len); if (!strcmp ((char *) str, (char *) str2)) { /* dsa-with-sha */ result = asn1_der_decoding_startEnd (cert2, der, der_len, "tbsCertificate", &start, &end); /* add the lines to calculate the sha on der[start]..der[end] */ len = sizeof (str) - 1; result = asn1_read_value (cert2, "signature", str, &len); /* compare the previous value to signature ( with issuer public key) */ } /* Use the next 3 lines to visit the certificate */ /* printf("-----------------\n"); asn1_visit_tree(cert2,""); printf("-----------------\n"); */ /* Clear the "certificate2" structure */ asn1_delete_structure (&cert2); }
/* Reads the DER signature from the certificate and allocates space and * returns them into signed_data. */ int _gnutls_x509_get_signature (ASN1_TYPE src, const char *src_name, gnutls_datum_t * signature) { int bits, result, len; signature->data = NULL; signature->size = 0; /* Read the signature */ bits = 0; result = asn1_read_value (src, src_name, NULL, &bits); if (result != ASN1_MEM_ERROR) { result = _gnutls_asn2err (result); gnutls_assert (); goto cleanup; } if (bits % 8 != 0) { gnutls_assert (); result = GNUTLS_E_CERTIFICATE_ERROR; goto cleanup; } len = bits / 8; signature->data = gnutls_malloc (len); if (signature->data == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; return result; } /* read the bit string of the signature */ bits = len; result = asn1_read_value (src, src_name, signature->data, &bits); if (result != ASN1_SUCCESS) { result = _gnutls_asn2err (result); gnutls_assert (); goto cleanup; } signature->size = len; return 0; cleanup: return result; }
/* Reads a value from an ASN1 tree, and puts the output * in an allocated variable in the given datum. * If str is non zero, then the output will be treated as * an octet string. */ int _gnutls_x509_read_value (ASN1_TYPE c, const char *root, gnutls_datum_t * ret, int str) { int len = 0, result; size_t slen; opaque *tmp = NULL; result = asn1_read_value (c, root, NULL, &len); if (result != ASN1_MEM_ERROR) { gnutls_assert (); result = _gnutls_asn2err (result); return result; } tmp = gnutls_malloc (len); if (tmp == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } result = asn1_read_value (c, root, tmp, &len); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Extract the OCTET STRING. */ if (str) { slen = len; result = _gnutls_x509_decode_octet_string (NULL, tmp, slen, tmp, &slen); if (result < 0) { gnutls_assert (); goto cleanup; } len = slen; } ret->data = tmp; ret->size = len; return 0; cleanup: gnutls_free (tmp); return result; }
/** * gnutls_x509_crl_get_extension_info - Get extension id and criticality * @crl: should contain a #gnutls_x509_crl_t structure * @indx: Specifies which extension OID to send, use zero to get the first one. * @oid: a pointer to a structure to hold the OID * @sizeof_oid: initially holds the maximum size of @oid, on return * holds actual size of @oid. * @critical: output variable with critical flag, may be NULL. * * This function will return the requested extension OID in the CRL, * and the critical flag for it. The extension OID will be stored as * a string in the provided buffer. Use * gnutls_x509_crl_get_extension_data() to extract the data. * * If the buffer provided is not long enough to hold the output, then * *@sizeof_oid is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will be * returned. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative value in case of an error. If your have reached the * last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE * will be returned. * * Since: 2.8.0 **/ int gnutls_x509_crl_get_extension_info (gnutls_x509_crl_t crl, int indx, void *oid, size_t * sizeof_oid, int *critical) { int result; char str_critical[10]; char name[ASN1_MAX_NAME_SIZE]; int len; if (!crl) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } snprintf (name, sizeof (name), "tbsCertList.crlExtensions.?%u.extnID", indx + 1); len = *sizeof_oid; result = asn1_read_value (crl->crl, name, oid, &len); *sizeof_oid = len; if (result == ASN1_ELEMENT_NOT_FOUND) return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; else if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } snprintf (name, sizeof (name), "tbsCertList.crlExtensions.?%u.critical", indx + 1); len = sizeof (str_critical); result = asn1_read_value (crl->crl, name, str_critical, &len); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } if (critical) { if (str_critical[0] == 'T') *critical = 1; else *critical = 0; } return 0; }
/* this function reads a (small) unsigned integer * from asn1 structs. Combines the read and the convertion * steps. */ int _gnutls_x509_read_uint (ASN1_TYPE node, const char *value, unsigned int *ret) { int len, result; opaque *tmpstr; len = 0; result = asn1_read_value (node, value, NULL, &len); if (result != ASN1_MEM_ERROR) { gnutls_assert (); return _gnutls_asn2err (result); } tmpstr = gnutls_malloc (len); if (tmpstr == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } result = asn1_read_value (node, value, tmpstr, &len); if (result != ASN1_SUCCESS) { gnutls_assert (); gnutls_free (tmpstr); return _gnutls_asn2err (result); } if (len == 1) *ret = tmpstr[0]; else if (len == 2) *ret = _gnutls_read_uint16 (tmpstr); else if (len == 3) *ret = _gnutls_read_uint24 (tmpstr); else if (len == 4) *ret = _gnutls_read_uint32 (tmpstr); else { gnutls_assert (); gnutls_free (tmpstr); return GNUTLS_E_INTERNAL_ERROR; } gnutls_free (tmpstr); return 0; }
time_t _gnutls_x509_get_time (ASN1_TYPE c2, const char *when) { char ttime[MAX_TIME]; char name[128]; time_t c_time = (time_t) - 1; int len, result; _gnutls_str_cpy (name, sizeof (name), when); len = sizeof (ttime) - 1; if ((result = asn1_read_value (c2, name, ttime, &len)) < 0) { gnutls_assert (); return (time_t) (-1); } /* CHOICE */ if (strcmp (ttime, "generalTime") == 0) { _gnutls_str_cat (name, sizeof (name), ".generalTime"); len = sizeof (ttime) - 1; result = asn1_read_value (c2, name, ttime, &len); if (result == ASN1_SUCCESS) c_time = _gnutls_x509_generalTime2gtime (ttime); } else { /* UTCTIME */ _gnutls_str_cat (name, sizeof (name), ".utcTime"); len = sizeof (ttime) - 1; result = asn1_read_value (c2, name, ttime, &len); if (result == ASN1_SUCCESS) c_time = _gnutls_x509_utcTime2gtime (ttime); } /* We cannot handle dates after 2031 in 32 bit machines. * a time_t of 64bits has to be used. */ if (result != ASN1_SUCCESS) { gnutls_assert (); return (time_t) (-1); } return c_time; }
/** * gnutls_x509_crl_get_extension_data - Get the specified extension data * @crl: should contain a #gnutls_x509_crl_t structure * @indx: Specifies which extension OID to send. Use zero to get the first one. * @data: a pointer to a structure to hold the data (may be null) * @sizeof_data: initially holds the size of @oid * * This function will return the requested extension data in the CRL. * The extension data will be stored as a string in the provided * buffer. * * Use gnutls_x509_crl_get_extension_info() to extract the OID and * critical flag. Use gnutls_x509_crl_get_extension_by_oid() instead, * if you want to get data indexed by the extension OID rather than * sequence. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative value in case of an error. If your have reached the * last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE * will be returned. * * Since: 2.8.0 **/ int gnutls_x509_crl_get_extension_data (gnutls_x509_crl_t crl, int indx, void *data, size_t * sizeof_data) { int result, len; char name[ASN1_MAX_NAME_SIZE]; if (!crl) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } snprintf (name, sizeof (name), "tbsCertList.crlExtensions.?%u.extnValue", indx + 1); len = *sizeof_data; result = asn1_read_value (crl->crl, name, data, &len); *sizeof_data = len; if (result == ASN1_ELEMENT_NOT_FOUND) return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; else if (result < 0) { gnutls_assert (); return _gnutls_asn2err (result); } return 0; }
/** * gnutls_x509_crl_get_authority_key_id: * @crl: should contain a #gnutls_x509_crl_t structure * @id: The place where the identifier will be copied * @id_size: Holds the size of the result field. * @critical: will be non-zero if the extension is marked as critical * (may be null) * * This function will return the CRL authority's key identifier. This * is obtained by the X.509 Authority Key identifier extension field * (2.5.29.35). Note that this function * only returns the keyIdentifier field of the extension and * %GNUTLS_E_X509_UNSUPPORTED_EXTENSION, if the extension contains * the name and serial number of the certificate. In that case * gnutls_x509_crl_get_authority_key_gn_serial() may be used. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error code in case of an error. * * Since: 2.8.0 **/ int gnutls_x509_crl_get_authority_key_id(gnutls_x509_crl_t crl, void *id, size_t * id_size, unsigned int *critical) { int result, len, ret; ASN1_TYPE c2; ret = _get_authority_key_id(crl, &c2, critical); if (ret < 0) return gnutls_assert_val(ret); len = *id_size; result = asn1_read_value(c2, "keyIdentifier", id, &len); *id_size = len; asn1_delete_structure(&c2); if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND) return gnutls_assert_val(GNUTLS_E_X509_UNSUPPORTED_EXTENSION); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } return 0; }
/* reads the curve from the certificate. * params[0-4]. It does NOT set params_nr. */ int _gnutls_x509_read_ecc_params (opaque * der, int dersize, gnutls_pk_params_st * params) { int ret; ASN1_TYPE spk = ASN1_TYPE_EMPTY; char oid[MAX_OID_SIZE]; int oid_size; if ((ret = asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.ECParameters", &spk)) != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (ret); } ret = asn1_der_decoding (&spk, der, dersize, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert (); ret = _gnutls_asn2err (ret); goto cleanup; } /* Read curve */ /* read the curve */ oid_size = sizeof(oid); ret = asn1_read_value(spk, "namedCurve", oid, &oid_size); if (ret != ASN1_SUCCESS) { gnutls_assert (); ret = _gnutls_asn2err (ret); goto cleanup; } params->flags = _gnutls_oid_to_ecc_curve(oid); if (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 cleanup; } ret = _gnutls_ecc_curve_fill_params(params->flags, params); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = 0; cleanup: asn1_delete_structure (&spk); return ret; }
/** * gnutls_x509_crq_get_version - This function returns the Certificate request's version number * @crq: should contain a gnutls_x509_crq_t structure * * This function will return the version of the specified Certificate request. * * Returns a negative value on error. * **/ int gnutls_x509_crq_get_version (gnutls_x509_crq_t crq) { opaque version[5]; int len, result; if (crq == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } len = sizeof (version); if ((result = asn1_read_value (crq->crq, "certificationRequestInfo.version", version, &len)) != ASN1_SUCCESS) { if (result == ASN1_ELEMENT_NOT_FOUND) return 1; /* the DEFAULT version */ gnutls_assert (); return _gnutls_asn2err (result); } return (int) version[0] + 1; }
/* Reads a value from an ASN1 tree, and puts the output * in an allocated variable in the given datum. * * Note that this function always allocates one plus * the required data size (and places a null byte). */ static int x509_read_value(ASN1_TYPE c, const char *root, gnutls_datum_t * ret, unsigned allow_null) { int len = 0, result; uint8_t *tmp = NULL; unsigned int etype; result = asn1_read_value_type(c, root, NULL, &len, &etype); if (result == 0 && allow_null == 0 && len == 0) { /* don't allow null strings */ return gnutls_assert_val(GNUTLS_E_ASN1_DER_ERROR); } if (result != ASN1_MEM_ERROR) { if (result != ASN1_SUCCESS || allow_null == 0 || len != 0) { gnutls_assert(); result = _gnutls_asn2err(result); return result; } } if (etype == ASN1_ETYPE_BIT_STRING) { len = (len + 7)/8; } tmp = gnutls_malloc((size_t) len + 1); if (tmp == NULL) { gnutls_assert(); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } if (len > 0) { result = asn1_read_value(c, root, tmp, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (etype == ASN1_ETYPE_BIT_STRING) { ret->size = (len+7) / 8; } else { ret->size = (unsigned) len; } } else { ret->size = 0; } tmp[ret->size] = 0; ret->data = tmp; return 0; cleanup: gnutls_free(tmp); return result; }
/** * gnutls_x509_crl_get_signature - Returns the CRL's signature * @crl: should contain a gnutls_x509_crl_t structure * @sig: a pointer where the signature part will be copied (may be null). * @sizeof_sig: initially holds the size of @sig * * This function will extract the signature field of a CRL. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. and a negative value on error. **/ int gnutls_x509_crl_get_signature (gnutls_x509_crl_t crl, char *sig, size_t * sizeof_sig) { int result; int bits; unsigned int len; if (crl == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } bits = 0; result = asn1_read_value (crl->crl, "signature", NULL, &bits); if (result != ASN1_MEM_ERROR) { gnutls_assert (); return _gnutls_asn2err (result); } if (bits % 8 != 0) { gnutls_assert (); return GNUTLS_E_CERTIFICATE_ERROR; } len = bits / 8; if (*sizeof_sig < len) { *sizeof_sig = bits / 8; return GNUTLS_E_SHORT_MEMORY_BUFFER; } result = asn1_read_value (crl->crl, "signature", sig, &len); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } return 0; }
/* This function will attempt to return the requested extension OID found in * the given X509v3 certificate. * * If you have passed the last extension, GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will * be returned. */ static int get_extension_oid(ASN1_TYPE asn, const char *root, unsigned indx, void *oid, size_t * sizeof_oid) { int k, result, len; char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE]; char extnID[MAX_OID_SIZE]; unsigned indx_counter = 0; k = 0; do { k++; snprintf(name, sizeof(name), "%s.?%u", root, k); _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 (indx == indx_counter++) { len = strlen(extnID) + 1; if (*sizeof_oid < (unsigned) len) { *sizeof_oid = len; gnutls_assert(); return GNUTLS_E_SHORT_MEMORY_BUFFER; } memcpy(oid, extnID, len); *sizeof_oid = len - 1; return 0; } } while (1); if (result == ASN1_ELEMENT_NOT_FOUND) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } else { gnutls_assert(); return _gnutls_asn2err(result); } }
int der_decode(const uint8_t *der, unsigned der_size, uint8_t *out, unsigned *out_size, char *realm, unsigned realm_size, int *error) { int ret, len; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; ret = asn1_create_element(_kkdcp_pkix1_asn, "KKDCP.KDC-PROXY-MESSAGE", &c2); if (ret != ASN1_SUCCESS) { *error = ret; return -1; } ret = asn1_der_decoding(&c2, der, der_size, NULL); if (ret != ASN1_SUCCESS) { *error = ret; ret = -1; goto cleanup; } len = *out_size; ret = asn1_read_value(c2, "kerb-message", out, &len); if (ret != ASN1_SUCCESS) { *error = ret; ret = -1; goto cleanup; } *out_size = len; len = realm_size; ret = asn1_read_value(c2, "target-domain", realm, &len); if (ret != ASN1_SUCCESS) { /* no realm was given */ realm[0] = 0; } ret = 0; cleanup: asn1_delete_structure(&c2); return ret; }
/* this function reads an integer * from asn1 structs. Combines the read and mpi_scan * steps. */ int _gnutls_x509_read_int (ASN1_TYPE node, const char *value, bigint_t * ret_mpi) { int result; opaque *tmpstr = NULL; int tmpstr_size; tmpstr_size = 0; result = asn1_read_value (node, value, NULL, &tmpstr_size); if (result != ASN1_MEM_ERROR) { gnutls_assert (); return _gnutls_asn2err (result); } tmpstr = gnutls_malloc (tmpstr_size); if (tmpstr == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } result = asn1_read_value (node, value, tmpstr, &tmpstr_size); if (result != ASN1_SUCCESS) { gnutls_assert (); gnutls_free (tmpstr); return _gnutls_asn2err (result); } result = _gnutls_mpi_scan (ret_mpi, tmpstr, tmpstr_size); gnutls_free (tmpstr); if (result < 0) { gnutls_assert (); return result; } return 0; }
/* Reads a value from an ASN1 tree, then interprets it as the provided * type of string and returns the output in an allocated variable. * * Note that this function always places a null character * at the end of a readable string value (which is not accounted into size) */ int _gnutls_x509_read_string(ASN1_TYPE c, const char *root, gnutls_datum_t * ret, unsigned int etype) { int len = 0, result; size_t slen; uint8_t *tmp = NULL; unsigned rtype; result = asn1_read_value_type(c, root, NULL, &len, &rtype); if (result != ASN1_MEM_ERROR) { gnutls_assert(); result = _gnutls_asn2err(result); return result; } if (rtype == ASN1_ETYPE_BIT_STRING) len /= 8; tmp = gnutls_malloc((size_t) len + 1); if (tmp == NULL) { gnutls_assert(); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } result = asn1_read_value(c, root, tmp, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (rtype == ASN1_ETYPE_BIT_STRING) len /= 8; /* Extract the STRING. */ slen = (size_t) len; result = _gnutls_x509_decode_string(etype, tmp, slen, ret); if (result < 0) { gnutls_assert(); goto cleanup; } gnutls_free(tmp); return 0; cleanup: gnutls_free(tmp); return result; }
/* Decodes an octet string. Leave string_type null for a normal * octet string. Otherwise put something like BMPString, PrintableString * etc. */ int _gnutls_x509_decode_octet_string (const char *string_type, const opaque * der, size_t der_size, opaque * output, size_t * output_size) { ASN1_TYPE c2 = ASN1_TYPE_EMPTY; int result, tmp_output_size; char strname[64]; if (string_type == NULL) _gnutls_str_cpy (strname, sizeof (strname), "PKIX1.pkcs-7-Data"); else { _gnutls_str_cpy (strname, sizeof (strname), "PKIX1."); _gnutls_str_cat (strname, sizeof (strname), string_type); } if ((result = asn1_create_element (_gnutls_get_pkix (), strname, &c2)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } result = asn1_der_decoding (&c2, der, der_size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } tmp_output_size = *output_size; result = asn1_read_value (c2, "", output, &tmp_output_size); *output_size = tmp_output_size; if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } result = 0; cleanup: if (c2) asn1_delete_structure (&c2); return result; }
/* extract the basicConstraints from the DER encoded extension */ int _gnutls_x509_ext_extract_basicConstraints (unsigned int *CA, int *pathLenConstraint, uint8_t * extnValue, int extnValueLen) { ASN1_TYPE ext = ASN1_TYPE_EMPTY; char str[128]; int len, result; if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.BasicConstraints", &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, "pathLenConstraint", (unsigned int*)pathLenConstraint); if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) *pathLenConstraint = -1; else if (result != GNUTLS_E_SUCCESS) { gnutls_assert (); asn1_delete_structure (&ext); return _gnutls_asn2err (result); } } /* the default value of cA is false. */ len = sizeof (str) - 1; result = asn1_read_value (ext, "cA", str, &len); if (result == ASN1_SUCCESS && strcmp (str, "TRUE") == 0) *CA = 1; else *CA = 0; asn1_delete_structure (&ext); 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; }
/** * gnutls_x509_crl_get_authority_key_gn_serial: * @crl: should contain a #gnutls_x509_crl_t structure * @seq: specifies the sequence number of the alt name (0 for the first one, 1 for the second etc.) * @alt: is the place where the alternative name will be copied to * @alt_size: holds the size of alt. * @alt_type: holds the type of the alternative name (one of gnutls_x509_subject_alt_name_t). * @serial: buffer to store the serial number (may be null) * @serial_size: Holds the size of the serial field (may be null) * @critical: will be non-zero if the extension is marked as critical (may be null) * * This function will return the X.509 authority key * identifier when stored as a general name (authorityCertIssuer) * and serial number. * * Because more than one general names might be stored * @seq can be used as a counter to request them all until * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned. * * Returns: Returns 0 on success, or an error code. * * Since: 3.0 **/ int gnutls_x509_crl_get_authority_key_gn_serial(gnutls_x509_crl_t crl, unsigned int seq, void *alt, size_t * alt_size, unsigned int *alt_type, void *serial, size_t * serial_size, unsigned int *critical) { int ret, result, len; ASN1_TYPE c2; ret = _get_authority_key_id(crl, &c2, critical); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_parse_general_name(c2, "authorityCertIssuer", seq, alt, alt_size, alt_type, 0); if (ret < 0) { ret = gnutls_assert_val(ret); goto fail; } if (serial) { len = *serial_size; result = asn1_read_value(c2, "authorityCertSerialNumber", serial, &len); *serial_size = len; if (result < 0) { ret = _gnutls_asn2err(result); goto fail; } } ret = 0; fail: asn1_delete_structure(&c2); return ret; }
/* Reads and returns the PK algorithm of the given certificate-like * ASN.1 structure. src_name should be something like "tbsCertificate.subjectPublicKeyInfo". */ int _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name, unsigned int *bits) { int result; int algo; char oid[64]; int len; gnutls_pk_params_st params; char name[128]; gnutls_pk_params_init(¶ms); _asnstr_append_name (name, sizeof (name), src_name, ".algorithm.algorithm"); len = sizeof (oid); result = asn1_read_value (src, name, oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } algo = _gnutls_x509_oid2pk_algorithm (oid); if (algo == GNUTLS_PK_UNKNOWN) { _gnutls_debug_log ("%s: unknown public key algorithm: %s\n", __func__, oid); } if (bits == NULL) { return algo; } /* Now read the parameters' bits */ result = _gnutls_get_asn_mpis(src, src_name, ¶ms); if (result < 0) return gnutls_assert_val(result); bits[0] = pubkey_to_bits(algo, ¶ms); gnutls_pk_params_release(¶ms); return algo; }
/* 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; }
/** * asn1_find_structure_from_oid: * @definitions: ASN1 definitions * @oidValue: value of the OID to search (e.g. "1.2.3.4"). * * Search the structure that is defined just after an OID definition. * * Returns: %NULL when @oidValue not found, otherwise the pointer to a * constant string that contains the element name defined just after * the OID. **/ const char * asn1_find_structure_from_oid (ASN1_TYPE definitions, const char *oidValue) { char definitionsName[ASN1_MAX_NAME_SIZE], name[2 * ASN1_MAX_NAME_SIZE + 1]; char value[ASN1_MAX_NAME_SIZE]; ASN1_TYPE p; int len; asn1_retCode result; if ((definitions == ASN1_TYPE_EMPTY) || (oidValue == NULL)) return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ strcpy (definitionsName, definitions->name); strcat (definitionsName, "."); /* search the OBJECT_ID into definitions */ p = definitions->down; while (p) { if ((type_field (p->type) == TYPE_OBJECT_ID) && (p->type & CONST_ASSIGN)) { strcpy (name, definitionsName); strcat (name, p->name); len = ASN1_MAX_NAME_SIZE; result = asn1_read_value (definitions, name, value, &len); if ((result == ASN1_SUCCESS) && (!strcmp (oidValue, value))) { p = p->right; if (p == NULL) /* reach the end of ASN1 definitions */ return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ return p->name; } } p = p->right; } return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ }
/* Here we only extract the KeyUsage field, from the DER encoded * extension. */ int _gnutls_x509_ext_extract_keyUsage (uint16_t * keyUsage, uint8_t * extnValue, int extnValueLen) { ASN1_TYPE ext = ASN1_TYPE_EMPTY; int len, result; uint8_t str[2]; str[0] = str[1] = 0; *keyUsage = 0; if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.KeyUsage", &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); } len = sizeof (str); result = asn1_read_value (ext, "", str, &len); if (result != ASN1_SUCCESS) { gnutls_assert (); asn1_delete_structure (&ext); return 0; } *keyUsage = str[0] | (str[1] << 8); asn1_delete_structure (&ext); return 0; }
/* extract an INTEGER from the DER encoded extension */ int _gnutls_x509_ext_extract_number (uint8_t * number, size_t * _nr_size, uint8_t * extnValue, int extnValueLen) { ASN1_TYPE ext = ASN1_TYPE_EMPTY; int result; int nr_size = *_nr_size; /* here it doesn't matter so much that we use CertificateSerialNumber. It is equal * to using INTEGER. */ if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.CertificateSerialNumber", &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); } /* the default value of cA is false. */ result = asn1_read_value (ext, "", number, &nr_size); if (result != ASN1_SUCCESS) result = _gnutls_asn2err (result); else result = 0; *_nr_size = nr_size; asn1_delete_structure (&ext); return result; }
/** * gnutls_x509_crl_get_version: * @crl: should contain a #gnutls_x509_crl_t structure * * This function will return the version of the specified CRL. * * Returns: The version number, or a negative error code on error. **/ int gnutls_x509_crl_get_version(gnutls_x509_crl_t crl) { uint8_t version[8]; int len, result; if (crl == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } len = sizeof(version); if ((result = asn1_read_value(crl->crl, "tbsCertList.version", version, &len)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } return (int) version[0] + 1; }
/** * gnutls_x509_crl_get_crt_serial - get the serial number of a revoked certificate * @crl: should contain a #gnutls_x509_crl_t structure * @indx: the index of the certificate to extract (starting from 0) * @serial: where the serial number will be copied * @serial_size: initially holds the size of serial * @t: if non null, will hold the time this certificate was revoked * * This function will retrieve the serial number of the specified, by * the index, revoked certificate. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. and a negative value on error. **/ int gnutls_x509_crl_get_crt_serial (gnutls_x509_crl_t crl, int indx, unsigned char *serial, size_t * serial_size, time_t * t) { int result, _serial_size; char serial_name[ASN1_MAX_NAME_SIZE]; char date_name[ASN1_MAX_NAME_SIZE]; if (crl == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } snprintf (serial_name, sizeof (serial_name), "tbsCertList.revokedCertificates.?%u.userCertificate", indx + 1); snprintf (date_name, sizeof (date_name), "tbsCertList.revokedCertificates.?%u.revocationDate", indx + 1); _serial_size = *serial_size; result = asn1_read_value (crl->crl, serial_name, serial, &_serial_size); *serial_size = _serial_size; if (result != ASN1_SUCCESS) { gnutls_assert (); if (result == ASN1_ELEMENT_NOT_FOUND) return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; return _gnutls_asn2err (result); } if (t) { *t = _gnutls_x509_get_time (crl->crl, date_name); } return 0; }
/** * 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; }
/** * gnutls_pkcs12_set_bag: * @pkcs12: should contain a gnutls_pkcs12_t structure * @bag: An initialized bag * * This function will insert a Bag into the PKCS12 structure. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ 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; }
/** * 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; }