/** * gnutls_pkcs11_privkey_import_url: * @pkey: The structure to store the parsed key * @url: a PKCS 11 url identifying the key * @flags: sequence of GNUTLS_PKCS_PRIVKEY_* * * This function will "import" a PKCS 11 URL identifying a private * key to the #gnutls_pkcs11_privkey_t structure. In reality since * in most cases keys cannot be exported, the private key structure * is being associated with the available operations on the token. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey, const char *url, unsigned int flags) { int ret; struct ck_function_list *module; struct ck_attribute *attr; ck_session_handle_t pks; ck_object_handle_t obj; struct ck_attribute a[4]; ck_key_type_t key_type; ret = pkcs11_url_to_info (url, &pkey->info); if (ret < 0) { gnutls_assert (); return ret; } pkey->flags = flags; attr = p11_kit_uri_get_attribute (pkey->info, CKA_CLASS); if (!attr || attr->value_len != sizeof (ck_object_class_t) || *(ck_object_class_t*)attr->value != CKO_PRIVATE_KEY) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } attr = p11_kit_uri_get_attribute (pkey->info, CKA_ID); if (!attr || !attr->value_len) { attr = p11_kit_uri_get_attribute (pkey->info, CKA_LABEL); if (!attr || !attr->value_len) { gnutls_assert (); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } } FIND_OBJECT (module, pks, obj, pkey); a[0].type = CKA_KEY_TYPE; a[0].value = &key_type; a[0].value_len = sizeof (key_type); if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK) { pkey->pk_algorithm = mech_to_pk(key_type); if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN) { _gnutls_debug_log("Cannot determine PKCS #11 key algorithm\n"); ret = GNUTLS_E_UNKNOWN_ALGORITHM; goto cleanup; } } ret = 0; cleanup: pkcs11_close_session (module, pks); 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 (0) 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); if (result < 0) { gnutls_assert(); goto cleanup; } result = 0; cleanup: if (c2) asn1_delete_structure(&c2); return result; }
/** * gnutls_pkcs12_generate_mac: * @pkcs12: should contain a gnutls_pkcs12_t structure * @pass: The password for the MAC * * This function will generate a MAC for the PKCS12 structure. * * 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) { 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; }
/* Encodes the bag into a SafeContents structure, and puts the output in * the given datum. Enc is set to non-zero if the data are encrypted; */ int _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; }
/* 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; 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 write_new_general_name (ASN1_TYPE ext, const char *ext_name, gnutls_x509_subject_alt_name_t type, const void *data, unsigned int data_size) { const char *str; int result; char name[128]; result = asn1_write_value (ext, ext_name, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } switch (type) { case GNUTLS_SAN_DNSNAME: str = "dNSName"; break; case GNUTLS_SAN_RFC822NAME: str = "rfc822Name"; break; case GNUTLS_SAN_URI: str = "uniformResourceIdentifier"; break; case GNUTLS_SAN_IPADDRESS: str = "iPAddress"; break; default: gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } if (ext_name[0] == 0) { /* no dot */ _gnutls_str_cpy (name, sizeof (name), "?LAST"); } else { _gnutls_str_cpy (name, sizeof (name), ext_name); _gnutls_str_cat (name, sizeof (name), ".?LAST"); } result = asn1_write_value (ext, name, str, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } _gnutls_str_cat (name, sizeof (name), "."); _gnutls_str_cat (name, sizeof (name), str); result = asn1_write_value (ext, name, data, data_size); if (result != ASN1_SUCCESS) { gnutls_assert (); asn1_delete_structure (&ext); return _gnutls_asn2err (result); } return 0; }
/** * gnutls_openpgp_key_get_name - Extracts the userID * @key: the structure that contains the OpenPGP public key. * @idx: the index of the ID to extract * @buf: a pointer to a structure to hold the name * @sizeof_buf: holds the size of 'buf' * * Extracts the userID from the parsed OpenPGP key. * * Returns 0 on success, and GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE * if the index of the ID does not exist. * **/ int gnutls_openpgp_key_get_name (gnutls_openpgp_key_t key, int idx, char *buf, size_t * sizeof_buf) { cdk_kbnode_t ctx = NULL, p; cdk_packet_t pkt = NULL; cdk_pkt_userid_t uid = NULL; int pos = 0; size_t size = 0; int rc = 0; if (!key || !buf) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (idx < 0 || idx > _gnutls_openpgp_count_key_names (key)) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } if (!idx) pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_USER_ID); else { pos = 0; while ((p = cdk_kbnode_walk (key->knode, &ctx, 0))) { pkt = cdk_kbnode_get_packet (p); if (pkt->pkttype == CDK_PKT_USER_ID && ++pos == idx) break; } } if (!pkt) { rc = GNUTLS_E_INTERNAL_ERROR; goto leave; } uid = pkt->pkt.user_id; if (uid->len >= *sizeof_buf) { gnutls_assert (); *sizeof_buf = uid->len + 1; rc = GNUTLS_E_SHORT_MEMORY_BUFFER; goto leave; } size = uid->len < *sizeof_buf ? uid->len : *sizeof_buf - 1; memcpy (buf, uid->name, size); buf[size] = '\0'; /* make sure it's a string */ if (uid->is_revoked) { rc = GNUTLS_E_OPENPGP_UID_REVOKED; goto leave; } leave: return rc; }
/** * gnutls_x509_crl_import: * @crl: The structure to store the parsed CRL. * @data: The DER or PEM encoded CRL. * @format: One of DER or PEM * * This function will convert the given DER or PEM encoded CRL * to the native #gnutls_x509_crl_t format. The output will be stored in 'crl'. * * If the CRL is PEM encoded it should have a header of "X509 CRL". * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_x509_crl_import(gnutls_x509_crl_t crl, const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format) { int result = 0; if (crl == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } _gnutls_free_datum(&crl->der); /* If the CRL is in PEM format then decode it */ if (format == GNUTLS_X509_FMT_PEM) { result = _gnutls_fbase64_decode(PEM_CRL, data->data, data->size, &crl->der); if (result < 0) { gnutls_assert(); return result; } } else { result = _gnutls_set_datum(&crl->der, data->data, data->size); if (result < 0) { gnutls_assert(); return result; } } if (crl->expanded) { result = crl_reinit(crl); if (result < 0) { gnutls_assert(); goto cleanup; } } crl->expanded = 1; result = asn1_der_decoding(&crl->crl, crl->der.data, crl->der.size, NULL); if (result != ASN1_SUCCESS) { result = _gnutls_asn2err(result); gnutls_assert(); goto cleanup; } result = _gnutls_x509_get_raw_field2(crl->crl, &crl->der, "tbsCertList.issuer.rdnSequence", &crl->raw_issuer_dn); if (result < 0) { gnutls_assert(); goto cleanup; } return 0; cleanup: _gnutls_free_datum(&crl->der); return result; }
/** * gnutls_x509_crl_list_import: * @crls: The structures to store the parsed CRLs. Must not be initialized. * @crl_max: Initially must hold the maximum number of crls. It will be updated with the number of crls available. * @data: The PEM encoded CRLs * @format: One of DER or PEM. * @flags: must be (0) or an OR'd sequence of gnutls_certificate_import_flags. * * This function will convert the given PEM encoded CRL list * to the native gnutls_x509_crl_t format. The output will be stored * in @crls. They will be automatically initialized. * * If the Certificate is PEM encoded it should have a header of "X509 CRL". * * Returns: the number of certificates read or a negative error value. * * Since: 3.0 **/ int gnutls_x509_crl_list_import(gnutls_x509_crl_t * crls, unsigned int *crl_max, const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format, unsigned int flags) { int size; const char *ptr; gnutls_datum_t tmp; int ret, nocopy = 0; unsigned int count = 0, j; if (format == GNUTLS_X509_FMT_DER) { if (*crl_max < 1) { *crl_max = 1; return GNUTLS_E_SHORT_MEMORY_BUFFER; } count = 1; /* import only the first one */ ret = gnutls_x509_crl_init(&crls[0]); if (ret < 0) { gnutls_assert(); goto error; } ret = gnutls_x509_crl_import(crls[0], data, format); if (ret < 0) { gnutls_assert(); goto error; } *crl_max = 1; return 1; } /* move to the certificate */ ptr = memmem(data->data, data->size, PEM_CRL_SEP, sizeof(PEM_CRL_SEP) - 1); if (ptr == NULL) { gnutls_assert(); return GNUTLS_E_BASE64_DECODING_ERROR; } count = 0; do { if (count >= *crl_max) { if (! (flags & GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED)) break; else nocopy = 1; } if (!nocopy) { ret = gnutls_x509_crl_init(&crls[count]); if (ret < 0) { gnutls_assert(); goto error; } tmp.data = (void *) ptr; tmp.size = data->size - (ptr - (char *) data->data); ret = gnutls_x509_crl_import(crls[count], &tmp, GNUTLS_X509_FMT_PEM); if (ret < 0) { gnutls_assert(); goto error; } } /* now we move ptr after the pem header */ ptr++; /* find the next certificate (if any) */ size = data->size - (ptr - (char *) data->data); if (size > 0) { ptr = memmem(ptr, size, PEM_CRL_SEP, sizeof(PEM_CRL_SEP) - 1); } else ptr = NULL; count++; } while (ptr != NULL); *crl_max = count; if (nocopy == 0) return count; else return GNUTLS_E_SHORT_MEMORY_BUFFER; error: for (j = 0; j < count; j++) gnutls_x509_crl_deinit(crls[j]); return ret; }
/** * gnutls_utf8_password_normalize: * @password: contain the UTF-8 formatted password * @plen: the length of the provided password * @out: the result in an null-terminated allocated string * @flags: should be zero * * This function will convert the provided UTF-8 password according * to the normalization rules in RFC7613. * * If the flag %GNUTLS_UTF8_IGNORE_ERRS is specified, any UTF-8 encoding * errors will be ignored, and in that case the output will be a copy of the input. * * Returns: %GNUTLS_E_INVALID_UTF8_STRING on invalid UTF-8 data, or 0 on success. * * Since: 3.5.7 **/ int gnutls_utf8_password_normalize(const unsigned char *password, unsigned plen, gnutls_datum_t *out, unsigned flags) { size_t ucs4_size = 0, nrm_size = 0; size_t final_size = 0; uint8_t *final = NULL; uint32_t *ucs4 = NULL; uint32_t *nrm = NULL; uint8_t *nrmu8 = NULL; int ret; if (plen == 0) { out->data = (uint8_t*)gnutls_strdup(""); out->size = 0; if (out->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); return 0; } /* check for invalid UTF-8 */ if (u8_check((uint8_t*)password, plen) != NULL) { gnutls_assert(); if (flags & GNUTLS_UTF8_IGNORE_ERRS) { raw_copy: out->data = gnutls_malloc(plen+1); if (out->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); out->size = plen; memcpy(out->data, password, plen); out->data[plen] = 0; return 0; } else { return GNUTLS_E_INVALID_UTF8_STRING; } } /* convert to UTF-32 */ ucs4 = u8_to_u32((uint8_t*)password, plen, NULL, &ucs4_size); if (ucs4 == NULL) { gnutls_assert(); ret = GNUTLS_E_PARSING_ERROR; goto fail; } ret = check_for_valid_freeformclass(ucs4, ucs4_size); if (ret < 0) { gnutls_assert(); if (flags & GNUTLS_UTF8_IGNORE_ERRS) { free(ucs4); goto raw_copy; } if (ret == GNUTLS_E_INVALID_UTF8_STRING) ret = GNUTLS_E_INVALID_PASSWORD_STRING; goto fail; } /* normalize to NFC */ nrm = u32_normalize(UNINORM_NFC, ucs4, ucs4_size, NULL, &nrm_size); if (nrm == NULL) { gnutls_assert(); ret = GNUTLS_E_INVALID_PASSWORD_STRING; goto fail; } /* convert back to UTF-8 */ final_size = 0; nrmu8 = u32_to_u8(nrm, nrm_size, NULL, &final_size); if (nrmu8 == NULL) { gnutls_assert(); ret = GNUTLS_E_INVALID_PASSWORD_STRING; goto fail; } /* copy to output with null terminator */ final = gnutls_malloc(final_size+1);
/* reads p,q and g * from the certificate (subjectPublicKey BIT STRING). * params[0-2]. It does NOT set params_nr. */ static int _gnutls_x509_read_dsa_params (opaque * der, int dersize, gnutls_pk_params_st * params) { int result; ASN1_TYPE spk = ASN1_TYPE_EMPTY; if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.Dss-Parms", &spk)) != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } result = asn1_der_decoding (&spk, der, dersize, NULL); if (result != ASN1_SUCCESS) { gnutls_assert (); asn1_delete_structure (&spk); return _gnutls_asn2err (result); } /* FIXME: If the parameters are not included in the certificate * then the issuer's parameters should be used. This is not * done yet. */ /* Read p */ if ((result = _gnutls_x509_read_int (spk, "p", ¶ms->params[0])) < 0) { gnutls_assert (); asn1_delete_structure (&spk); return GNUTLS_E_ASN1_GENERIC_ERROR; } /* Read q */ if ((result = _gnutls_x509_read_int (spk, "q", ¶ms->params[1])) < 0) { gnutls_assert (); asn1_delete_structure (&spk); _gnutls_mpi_release (¶ms->params[0]); return GNUTLS_E_ASN1_GENERIC_ERROR; } /* Read g */ if ((result = _gnutls_x509_read_int (spk, "g", ¶ms->params[2])) < 0) { gnutls_assert (); asn1_delete_structure (&spk); _gnutls_mpi_release (¶ms->params[0]); _gnutls_mpi_release (¶ms->params[1]); return GNUTLS_E_ASN1_GENERIC_ERROR; } asn1_delete_structure (&spk); return 0; }
int _gnutls_recv_client_certificate (gnutls_session_t session) { gnutls_buffer_st buf; int ret = 0; int optional; if (session->internals.auth_struct->gnutls_process_client_certificate == NULL) return 0; /* if we have not requested a certificate then just return */ if (session->internals.send_cert_req == 0) { return 0; } if (session->internals.send_cert_req == GNUTLS_CERT_REQUIRE) optional = MANDATORY_PACKET; else optional = OPTIONAL_PACKET; ret = _gnutls_recv_handshake (session, GNUTLS_HANDSHAKE_CERTIFICATE_PKT, optional, &buf); if (ret < 0) { /* Handle the case of old SSL3 clients who send * a warning alert instead of an empty certificate to indicate * no certificate. */ if (optional == OPTIONAL_PACKET && ret == GNUTLS_E_WARNING_ALERT_RECEIVED && gnutls_protocol_get_version (session) == GNUTLS_SSL3 && gnutls_alert_get (session) == GNUTLS_A_SSL3_NO_CERTIFICATE) { /* SSL3 does not send an empty certificate, * but this alert. So we just ignore it. */ gnutls_assert (); return 0; } /* certificate was required */ if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) && optional == MANDATORY_PACKET) { gnutls_assert (); return GNUTLS_E_NO_CERTIFICATE_FOUND; } return ret; } if (ret == 0 && buf.length == 0 && optional == OPTIONAL_PACKET) { /* Client has not sent the certificate message. * well I'm not sure we should accept this * behaviour. */ gnutls_assert (); ret = 0; goto cleanup; } ret = session->internals. auth_struct->gnutls_process_client_certificate (session, buf.data, buf.length); if (ret < 0 && ret != GNUTLS_E_NO_CERTIFICATE_FOUND) { gnutls_assert (); goto cleanup; } /* ok we should expect a certificate verify message now */ if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND && optional == OPTIONAL_PACKET) ret = 0; else session->key->certificate_requested = 1; cleanup: _gnutls_buffer_clear(&buf); return ret; }
/** * gnutls_pkcs11_privkey_generate: * @url: a token URL * @pk: the public key algorithm * @bits: the security bits * @label: a label * @flags: should be zero * * This function will generate a private key in the specified * by the @url token. The pivate key will be generate within * the token and will not be exportable. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.0 **/ int gnutls_pkcs11_privkey_generate (const char* url, gnutls_pk_algorithm_t pk, unsigned int bits, const char* label, unsigned int flags) { int ret; const ck_bool_t tval = 1; const ck_bool_t fval = 0; struct ck_function_list *module; ck_session_handle_t pks = 0; struct p11_kit_uri *info = NULL; ck_rv_t rv; struct ck_attribute a[10], p[10]; ck_object_handle_t pub, priv; unsigned long _bits = bits; int a_val, p_val; struct ck_mechanism mech; ret = pkcs11_url_to_info (url, &info); if (ret < 0) { gnutls_assert (); return ret; } ret = pkcs11_open_session (&module, &pks, info, SESSION_WRITE | pkcs11_obj_flags_to_int (flags)); p11_kit_uri_free (info); if (ret < 0) { gnutls_assert (); goto cleanup; } /* a holds the public key template * and p the private key */ a_val = p_val = 0; mech.parameter = NULL; mech.parameter_len = 0; mech.mechanism = pk_to_genmech(pk); switch(pk) { case GNUTLS_PK_RSA: p[p_val].type = CKA_DECRYPT; p[p_val].value = (void*)&tval; p[p_val].value_len = sizeof (tval); p_val++; p[p_val].type = CKA_SIGN; p[p_val].value = (void*)&tval; p[p_val].value_len = sizeof (tval); p_val++; a[a_val].type = CKA_ENCRYPT; a[a_val].value = (void*)&tval; a[a_val].value_len = sizeof (tval); a_val++; a[a_val].type = CKA_VERIFY; a[a_val].value = (void*)&tval; a[a_val].value_len = sizeof (tval); a_val++; a[a_val].type = CKA_MODULUS_BITS; a[a_val].value = &_bits; a[a_val].value_len = sizeof (_bits); a_val++; break; case GNUTLS_PK_DSA: p[p_val].type = CKA_SIGN; p[p_val].value = (void*)&tval; p[p_val].value_len = sizeof (tval); p_val++; a[a_val].type = CKA_VERIFY; a[a_val].value = (void*)&tval; a[a_val].value_len = sizeof (tval); a_val++; a[a_val].type = CKA_MODULUS_BITS; a[a_val].value = &_bits; a[a_val].value_len = sizeof (_bits); a_val++; break; case GNUTLS_PK_EC: p[p_val].type = CKA_SIGN; p[p_val].value = (void*)&tval; p[p_val].value_len = sizeof (tval); p_val++; a[a_val].type = CKA_VERIFY; a[a_val].value = (void*)&tval; a[a_val].value_len = sizeof (tval); a_val++; a[a_val].type = CKA_MODULUS_BITS; a[a_val].value = &_bits; a[a_val].value_len = sizeof (_bits); a_val++; break; default: ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); goto cleanup; } /* a private key is set always as private unless * requested otherwise */ if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) { p[p_val].type = CKA_PRIVATE; p[p_val].value = (void*)&fval; p[p_val].value_len = sizeof(fval); p_val++; } else { p[p_val].type = CKA_PRIVATE; p[p_val].value = (void*)&tval; p[p_val].value_len = sizeof (tval); p_val++; } p[p_val].type = CKA_TOKEN; p[p_val].value = (void *)&tval; p[p_val].value_len = sizeof (tval); p_val++; if (label) { p[p_val].type = CKA_LABEL; p[p_val].value = (void*)label; p[p_val].value_len = strlen (label); p_val++; a[a_val].type = CKA_LABEL; a[a_val].value = (void*)label; a[a_val].value_len = strlen (label); a_val++; } if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE) { p[p_val].type = CKA_SENSITIVE; p[p_val].value = (void*)&tval; p[p_val].value_len = sizeof (tval); p_val++; } else { p[p_val].type = CKA_SENSITIVE; p[p_val].value = (void*)&fval; p[p_val].value_len = sizeof (fval); p_val++; } rv = pkcs11_generate_key_pair( module, pks, &mech, a, a_val, p, p_val, &pub, &priv); if (rv != CKR_OK) { gnutls_assert (); _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv)); ret = pkcs11_rv_to_err (rv); goto cleanup; } cleanup: if (pks != 0) pkcs11_close_session (module, pks); return ret; }
/*- * _gnutls_pkcs11_privkey_decrypt_data: * @key: Holds the key * @flags: should be 0 for now * @ciphertext: holds the data to be signed * @plaintext: will contain the plaintext, allocated with gnutls_malloc() * * This function will decrypt the given data using the public key algorithm * supported by the private key. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. -*/ int _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key, unsigned int flags, const gnutls_datum_t * ciphertext, gnutls_datum_t * plaintext) { ck_rv_t rv; int ret; struct ck_mechanism mech; unsigned long siglen; struct ck_function_list *module; ck_session_handle_t pks; ck_object_handle_t obj; FIND_OBJECT (module, pks, obj, key); if (key->pk_algorithm != GNUTLS_PK_RSA) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); mech.mechanism = CKM_RSA_PKCS; mech.parameter = NULL; mech.parameter_len = 0; /* Initialize signing operation; using the private key discovered * earlier. */ rv = pkcs11_decrypt_init (module, pks, &mech, obj); if (rv != CKR_OK) { gnutls_assert (); ret = pkcs11_rv_to_err (rv); goto cleanup; } /* Work out how long the plaintext must be: */ rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size, NULL, &siglen); if (rv != CKR_OK) { gnutls_assert (); ret = pkcs11_rv_to_err (rv); goto cleanup; } plaintext->data = gnutls_malloc (siglen); plaintext->size = siglen; rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size, plaintext->data, &siglen); if (rv != CKR_OK) { gnutls_free (plaintext->data); gnutls_assert (); ret = pkcs11_rv_to_err (rv); goto cleanup; } plaintext->size = siglen; ret = 0; cleanup: pkcs11_close_session (module, pks); return ret; }
static int set_extension (ASN1_TYPE asn, const char *root, const char *ext_id, const gnutls_datum_t * ext_data, unsigned int critical) { int result; int k, len; char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE]; char extnID[128]; /* Find the index of the given extension. */ k = 0; do { k++; if (root[0] != 0) snprintf (name, sizeof (name), "%s.?%u", root, k); else snprintf (name, sizeof (name), "?%u", k); len = sizeof (extnID) - 1; result = asn1_read_value (asn, name, extnID, &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, ext_id) == 0) { /* extension was found */ return overwrite_extension (asn, root, k, ext_data, critical); } } while (0); } while (1); if (result == ASN1_ELEMENT_NOT_FOUND) { return add_extension (asn, root, ext_id, ext_data, critical); } else { gnutls_assert (); return _gnutls_asn2err (result); } return 0; }
/** * gnutls_x509_crl_iter_crt_serial: * @crl: should contain a #gnutls_x509_crl_t structure * @iter: A pointer to an iterator (initially the iterator should be %NULL) * @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 performs the same as gnutls_x509_crl_get_crt_serial(), * but reads sequentially and keeps state in the iterator * between calls. That allows it to provide better performance in sequences * with many elements (50000+). * * When past the last element is accessed %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE * is returned and the iterator is reset. * * After use, the iterator must be deinitialized using gnutls_x509_crl_iter_deinit(). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_x509_crl_iter_crt_serial(gnutls_x509_crl_t crl, gnutls_x509_crl_iter_t *iter, 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 || iter == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } if (*iter == NULL) { *iter = gnutls_calloc(1, sizeof(struct gnutls_x509_crl_iter)); if (*iter == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); } if ((*iter)->rcache == NULL) { (*iter)->rcache = asn1_find_node (crl->crl, "tbsCertList.revokedCertificates.?1"); (*iter)->rcache_idx = 1; } else { snprintf(serial_name, sizeof(serial_name), "?%d", (*iter)->rcache_idx); (*iter)->rcache = asn1_find_node ((*iter)->rcache, serial_name); } if ((*iter)->rcache == NULL) { /* reset */ (*iter)->rcache = NULL; return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); } snprintf(serial_name, sizeof(serial_name), "?%d.userCertificate", (*iter)->rcache_idx); _serial_size = *serial_size; result = asn1_read_value((*iter)->rcache, serial_name, serial, &_serial_size); *serial_size = _serial_size; if (result != ASN1_SUCCESS) { gnutls_assert(); if (result == ASN1_ELEMENT_NOT_FOUND) { /* reset */ (*iter)->rcache = NULL; return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } return _gnutls_asn2err(result); } if (t) { snprintf(date_name, sizeof(date_name), "?%d.revocationDate", (*iter)->rcache_idx); *t = _gnutls_x509_get_time((*iter)->rcache, date_name, 0); } (*iter)->rcache_idx++; return 0; }
int _gnutls_x509_crq_set_extension (gnutls_x509_crq_t crq, const char *ext_id, const gnutls_datum_t * ext_data, unsigned int critical) { unsigned char *extensions = NULL; size_t extensions_size = 0; gnutls_datum_t der; ASN1_TYPE c2; int result; result = gnutls_x509_crq_get_attribute_by_oid (crq, "1.2.840.113549.1.9.14", 0, NULL, &extensions_size); if (result == GNUTLS_E_SHORT_MEMORY_BUFFER) { extensions = gnutls_malloc (extensions_size); if (extensions == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } result = gnutls_x509_crq_get_attribute_by_oid (crq, "1.2.840.113549.1.9.14", 0, extensions, &extensions_size); } if (result < 0) { if (result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { extensions_size = 0; } else { gnutls_assert (); gnutls_free (extensions); return result; } } result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.Extensions", &c2); if (result != ASN1_SUCCESS) { gnutls_assert (); gnutls_free (extensions); return _gnutls_asn2err (result); } if (extensions_size > 0) { result = asn1_der_decoding (&c2, extensions, extensions_size, NULL); gnutls_free (extensions); if (result != ASN1_SUCCESS) { gnutls_assert (); asn1_delete_structure (&c2); return _gnutls_asn2err (result); } } result = set_extension (c2, "", ext_id, ext_data, critical); if (result < 0) { gnutls_assert (); asn1_delete_structure (&c2); return result; } result = _gnutls_x509_der_encode (c2, "", &der, 0); asn1_delete_structure (&c2); if (result < 0) { gnutls_assert (); return result; } result = gnutls_x509_crq_set_attribute_by_oid (crq, "1.2.840.113549.1.9.14", der.data, der.size); gnutls_free (der.data); if (result < 0) { gnutls_assert (); return result; } return 0; }
/* Creates and encodes the CRL Distribution points. data_string should be a name * and type holds the type of the name. * reason_flags should be an or'ed sequence of GNUTLS_CRL_REASON_*. * */ int _gnutls_x509_ext_gen_crl_dist_points (gnutls_x509_subject_alt_name_t type, const void *data, unsigned int data_size, unsigned int reason_flags, gnutls_datum_t * der_ext) { ASN1_TYPE ext = ASN1_TYPE_EMPTY; gnutls_datum_t gnames = { NULL, 0 }; int result; uint8_t reasons[2]; reasons[0] = reason_flags & 0xff; reasons[1] = reason_flags >> 8; result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.CRLDistributionPoints", &ext); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } result = asn1_write_value (ext, "", "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if (reason_flags) { result = asn1_write_value (ext, "?LAST.reasons", reasons, 9); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } } else { result = asn1_write_value (ext, "?LAST.reasons", NULL, 0); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } } result = asn1_write_value (ext, "?LAST.cRLIssuer", NULL, 0); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* When used as type CHOICE. */ result = asn1_write_value (ext, "?LAST.distributionPoint", "fullName", 1); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } #if 0 /* only needed in old code (where defined as SEQUENCE OF) */ asn1_write_value (ext, "?LAST.distributionPoint.nameRelativeToCRLIssuer", NULL, 0); #endif result = write_new_general_name (ext, "?LAST.distributionPoint.fullName", type, data, data_size); if (result < 0) { gnutls_assert (); goto cleanup; } result = _gnutls_x509_der_encode (ext, "", der_ext, 0); if (result < 0) { gnutls_assert (); goto cleanup; } result = 0; cleanup: _gnutls_free_datum (&gnames); asn1_delete_structure (&ext); return result; }
/** * gnutls_openpgp_key_export - This function will export a RAW or BASE64 encoded key * @key: Holds the key. * @format: One of gnutls_openpgp_key_fmt_t elements. * @output_data: will contain the key base64 encoded or raw * @output_data_size: holds the size of output_data (and will be replaced by the actual size of parameters) * * This function will convert the given key to RAW or Base64 format. * If the buffer provided is not long enough to hold the output, then * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned. * * Returns 0 on success. * **/ int gnutls_openpgp_key_export (gnutls_openpgp_key_t key, gnutls_openpgp_key_fmt_t format, void *output_data, size_t * output_data_size) { int rc; size_t input_data_size = *output_data_size; rc = cdk_kbnode_write_to_mem (key->knode, output_data, output_data_size); if (rc) { rc = _gnutls_map_cdk_rc (rc); gnutls_assert (); return rc; } if (format == GNUTLS_OPENPGP_FMT_BASE64) { cdk_stream_t s; s = cdk_stream_tmp_from_mem (output_data, *output_data_size); if (s == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } cdk_stream_tmp_set_mode (s, 1); rc = cdk_stream_set_armor_flag (s, CDK_ARMOR_PUBKEY); if (rc) { rc = _gnutls_map_cdk_rc (rc); gnutls_assert (); cdk_stream_close (s); return rc; } *output_data_size = input_data_size; rc = cdk_stream_read (s, output_data, *output_data_size); if (rc == EOF) { gnutls_assert (); cdk_stream_close (s); return GNUTLS_E_INTERNAL_ERROR; } *output_data_size = rc; if (*output_data_size != cdk_stream_get_length (s)) { *output_data_size = cdk_stream_get_length (s); cdk_stream_close (s); gnutls_assert (); return GNUTLS_E_SHORT_MEMORY_BUFFER; } cdk_stream_close (s); } return 0; }
/* extract the proxyCertInfo from the DER encoded extension */ int _gnutls_x509_ext_extract_proxyCertInfo (int *pathLenConstraint, char **policyLanguage, char **policy, size_t * sizeof_policy, opaque * 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", 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, 0); if (result < 0) { gnutls_assert (); asn1_delete_structure (&ext); return result; } if (policyLanguage) *policyLanguage = gnutls_strdup (value.data); result = _gnutls_x509_read_value (ext, "proxyPolicy.policy", &value, 0); 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 = value.data; if (sizeof_policy) *sizeof_policy = value.size; } asn1_delete_structure (&ext); return 0; }
static int 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; }
/* generate the proxyCertInfo in a DER encoded extension */ int _gnutls_x509_ext_gen_proxyCertInfo (int pathLenConstraint, const char *policyLanguage, const char *policy, size_t sizeof_policy, gnutls_datum_t * der_ext) { ASN1_TYPE ext = ASN1_TYPE_EMPTY; int result; result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.ProxyCertInfo", &ext); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } if (pathLenConstraint < 0) { result = asn1_write_value (ext, "pCPathLenConstraint", NULL, 0); if (result < 0) result = _gnutls_asn2err (result); } else result = _gnutls_x509_write_uint32 (ext, "pCPathLenConstraint", pathLenConstraint); if (result < 0) { gnutls_assert (); asn1_delete_structure (&ext); return result; } result = asn1_write_value (ext, "proxyPolicy.policyLanguage", policyLanguage, 1); if (result < 0) { gnutls_assert (); asn1_delete_structure (&ext); return _gnutls_asn2err (result); } result = asn1_write_value (ext, "proxyPolicy.policy", policy, sizeof_policy); if (result < 0) { gnutls_assert (); asn1_delete_structure (&ext); return _gnutls_asn2err (result); } result = _gnutls_x509_der_encode (ext, "", der_ext, 0); asn1_delete_structure (&ext); if (result < 0) { gnutls_assert (); return result; } return 0; }
/** * gnutls_pkcs12_simple_parse: * @p12: the PKCS12 blob. * @password: optional password used to decrypt PKCS12 blob, bags and keys. * @key: a structure to store the parsed private key. * @chain: the corresponding to key certificate chain (may be %NULL) * @chain_len: will be updated with the number of additional (may be %NULL) * @extra_certs: optional pointer to receive an array of additional * certificates found in the PKCS12 blob (may be %NULL). * @extra_certs_len: will be updated with the number of additional * certs (may be %NULL). * @crl: an optional structure to store the parsed CRL (may be %NULL). * @flags: should be zero or one of GNUTLS_PKCS12_SP_* * * This function parses a PKCS12 blob in @p12blob and extracts the * private key, the corresponding certificate chain, and any additional * certificates and a CRL. * * The @extra_certs_ret and @extra_certs_len parameters are optional * and both may be set to %NULL. If either is non-%NULL, then both must * be set. * * Encrypted PKCS12 bags and PKCS8 private keys are supported. However, * only password based security, and the same password for all * operations, are supported. * * A PKCS12 file may contain many keys and/or certificates, and there * is no way to identify which key/certificate pair you want. You * should make sure the PKCS12 file only contain one key/certificate * pair and/or one CRL. * * It is believed that the limitations of this function are acceptable * for common usage, and that any more flexibility would introduce * complexity that would make it harder to use this functionality at * all. * * If the provided structure has encrypted fields but no password * is provided then this function returns %GNUTLS_E_DECRYPTION_FAILED. * * Note that normally the chain constructed does not include self signed * certificates, to comply with TLS' requirements. If, however, the flag * %GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED is specified then * self signed certificates will be included in the chain. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * 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_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; } /* fallthrough */ 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; }
/* 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, int indx, void *oid, size_t * sizeof_oid) { int k, result, len; char name[ASN1_MAX_NAME_SIZE], name2[ASN1_MAX_NAME_SIZE]; char str[1024]; char extnID[128]; int indx_counter = 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 (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 (0); } while (1); if (result == ASN1_ELEMENT_NOT_FOUND) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } else { gnutls_assert (); return _gnutls_asn2err (result); } }
/* 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_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; }
/* This function will attempt to set the requested extension in * the given X509v3 certificate. * * Critical will be either 0 or 1. */ static int add_extension (ASN1_TYPE asn, const char *root, const char *extension_id, const gnutls_datum_t * ext_data, unsigned int critical) { int result; const char *str; char name[ASN1_MAX_NAME_SIZE]; snprintf (name, sizeof (name), "%s", root); /* Add a new extension in the list. */ result = asn1_write_value (asn, name, "NEW", 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } if (root[0] != 0) snprintf (name, sizeof (name), "%s.?LAST.extnID", root); else snprintf (name, sizeof (name), "?LAST.extnID"); result = asn1_write_value (asn, name, extension_id, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } if (critical == 0) str = "FALSE"; else str = "TRUE"; if (root[0] != 0) snprintf (name, sizeof (name), "%s.?LAST.critical", root); else snprintf (name, sizeof (name), "?LAST.critical"); result = asn1_write_value (asn, name, str, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } if (root[0] != 0) snprintf (name, sizeof (name), "%s.?LAST.extnValue", root); else snprintf (name, sizeof (name), "?LAST.extnValue"); result = _gnutls_x509_write_value (asn, name, ext_data, 0); if (result < 0) { gnutls_assert (); return result; } return 0; }
/** * 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 (0) 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; }
static 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, 0); 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); } }
/** * 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 (0) is returned, otherwise a * negative error value. **/ 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; }
/*- * _gnutls_pkcs11_privkey_sign_hash: * @key: Holds the key * @hash: holds the data to be signed (should be output of a hash) * @signature: will contain the signature allocated with gnutls_malloc() * * This function will sign the given data using a signature algorithm * supported by the private key. It is assumed that the given data * are the output of a hash function. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. -*/ int _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key, const gnutls_datum_t * hash, gnutls_datum_t * signature) { ck_rv_t rv; int ret; struct ck_mechanism mech; unsigned long siglen; struct ck_function_list *module; ck_session_handle_t pks; ck_object_handle_t obj; FIND_OBJECT (module, pks, obj, key); mech.mechanism = pk_to_mech(key->pk_algorithm); mech.parameter = NULL; mech.parameter_len = 0; /* Initialize signing operation; using the private key discovered * earlier. */ rv = pkcs11_sign_init (module, pks, &mech, obj); if (rv != CKR_OK) { gnutls_assert (); ret = pkcs11_rv_to_err (rv); goto cleanup; } /* Work out how long the signature must be: */ rv = pkcs11_sign (module, pks, hash->data, hash->size, NULL, &siglen); if (rv != CKR_OK) { gnutls_assert (); ret = pkcs11_rv_to_err (rv); goto cleanup; } signature->data = gnutls_malloc (siglen); signature->size = siglen; rv = pkcs11_sign (module, pks, hash->data, hash->size, signature->data, &siglen); if (rv != CKR_OK) { gnutls_free (signature->data); gnutls_assert (); ret = pkcs11_rv_to_err (rv); goto cleanup; } signature->size = siglen; if (key->pk_algorithm == GNUTLS_PK_EC || key->pk_algorithm == GNUTLS_PK_DSA) { bigint_t r,s; if (siglen % 2 != 0) { gnutls_assert(); ret = GNUTLS_E_PK_SIGN_FAILED; goto cleanup; } ret = read_rs(&r, &s, signature->data, signature->size); if (ret < 0) { gnutls_assert(); goto cleanup; } gnutls_free(signature->data); ret = _gnutls_encode_ber_rs (signature, r, s); _gnutls_mpi_release(&r); _gnutls_mpi_release(&s); if (ret < 0) { gnutls_assert(); goto cleanup; } } ret = 0; cleanup: pkcs11_close_session (module, pks); return ret; }