/* returns error if the certificate has different algorithm than * the given key parameters. */ static int _gnutls_check_key_cert_match (gnutls_certificate_credentials_t res) { gnutls_datum_t cid; gnutls_datum_t kid; unsigned pk = res->cert_list[res->ncerts - 1][0].subject_pk_algorithm; if (res->pkey[res->ncerts - 1].pk_algorithm != pk) { gnutls_assert (); return GNUTLS_E_CERTIFICATE_KEY_MISMATCH; } if (pk == GNUTLS_PK_RSA) { _gnutls_x509_write_rsa_params (res->pkey[res->ncerts - 1].params, res->pkey[res->ncerts - 1].params_size, &kid); _gnutls_x509_write_rsa_params (res-> cert_list[res->ncerts - 1][0].params, res->cert_list[res->ncerts - 1][0].params_size, &cid); } else if (pk == GNUTLS_PK_DSA) { _gnutls_x509_write_dsa_params (res->pkey[res->ncerts - 1].params, res->pkey[res->ncerts - 1].params_size, &kid); _gnutls_x509_write_dsa_params (res-> cert_list[res->ncerts - 1][0].params, res->cert_list[res->ncerts - 1][0].params_size, &cid); } if (cid.size != kid.size) { gnutls_assert (); _gnutls_free_datum (&kid); _gnutls_free_datum (&cid); return GNUTLS_E_CERTIFICATE_KEY_MISMATCH; } if (memcmp (kid.data, cid.data, kid.size) != 0) { gnutls_assert (); _gnutls_free_datum (&kid); _gnutls_free_datum (&cid); return GNUTLS_E_CERTIFICATE_KEY_MISMATCH; } _gnutls_free_datum (&kid); _gnutls_free_datum (&cid); return 0; }
/** * gnutls_x509_privkey_get_key_id - Return unique ID of the key's parameters * @key: Holds the key * @flags: should be 0 for now * @output_data: will contain the key ID * @output_data_size: holds the size of output_data (and will be * replaced by the actual size of parameters) * * This function will return a unique ID the depends on the public key * parameters. This ID can be used in checking whether a certificate * corresponds to the given key. * * If the buffer provided is not long enough to hold the output, then * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will * be returned. The output will normally be a SHA-1 hash output, * which is 20 bytes. * * Return value: In case of failure a negative value will be * returned, and 0 on success. * **/ int gnutls_x509_privkey_get_key_id (gnutls_x509_privkey_t key, unsigned int flags, unsigned char *output_data, size_t * output_data_size) { int result; GNUTLS_HASH_HANDLE hd; gnutls_datum_t der = { NULL, 0 }; if (key == NULL || key->crippled) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (*output_data_size < 20) { gnutls_assert (); *output_data_size = 20; return GNUTLS_E_SHORT_MEMORY_BUFFER; } if (key->pk_algorithm == GNUTLS_PK_RSA) { result = _gnutls_x509_write_rsa_params (key->params, key->params_size, &der); if (result < 0) { gnutls_assert (); goto cleanup; } } else if (key->pk_algorithm == GNUTLS_PK_DSA) { result = _gnutls_x509_write_dsa_public_key (key->params, key->params_size, &der); if (result < 0) { gnutls_assert (); goto cleanup; } } else return GNUTLS_E_INTERNAL_ERROR; hd = _gnutls_hash_init (GNUTLS_MAC_SHA1); if (hd == GNUTLS_HASH_FAILED) { gnutls_assert (); result = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } _gnutls_hash (hd, der.data, der.size); _gnutls_hash_deinit (hd, output_data); *output_data_size = 20; result = 0; cleanup: _gnutls_free_datum (&der); return result; }
/* Encodes and copies the private key parameters into a * subjectPublicKeyInfo structure. * */ int _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst, const char *dst_name, gnutls_pk_algorithm_t pk_algorithm, bigint_t * params, int params_size) { const char *pk; gnutls_datum_t der = { NULL, 0 }; int result; char name[128]; pk = _gnutls_x509_pk_to_oid (pk_algorithm); if (pk == NULL) { gnutls_assert (); return GNUTLS_E_UNKNOWN_PK_ALGORITHM; } /* write the OID */ _asnstr_append_name (name, sizeof (name), dst_name, ".algorithm.algorithm"); result = asn1_write_value (dst, name, pk, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } if (pk_algorithm == GNUTLS_PK_RSA) { /* disable parameters, which are not used in RSA. */ _asnstr_append_name (name, sizeof (name), dst_name, ".algorithm.parameters"); result = asn1_write_value (dst, name, ASN1_NULL, ASN1_NULL_SIZE); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } result = _gnutls_x509_write_rsa_params (params, params_size, &der); if (result < 0) { gnutls_assert (); return result; } /* Write the DER parameters. (in bits) */ _asnstr_append_name (name, sizeof (name), dst_name, ".subjectPublicKey"); result = asn1_write_value (dst, name, der.data, der.size * 8); _gnutls_free_datum (&der); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } } else if (pk_algorithm == GNUTLS_PK_DSA) { result = _gnutls_x509_write_dsa_params (params, params_size, &der); if (result < 0) { gnutls_assert (); return result; } /* Write the DER parameters. */ _asnstr_append_name (name, sizeof (name), dst_name, ".algorithm.parameters"); result = asn1_write_value (dst, name, der.data, der.size); _gnutls_free_datum (&der); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } result = _gnutls_x509_write_dsa_public_key (params, params_size, &der); if (result < 0) { gnutls_assert (); return result; } _asnstr_append_name (name, sizeof (name), dst_name, ".subjectPublicKey"); result = asn1_write_value (dst, name, der.data, der.size * 8); _gnutls_free_datum (&der); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } } else return GNUTLS_E_UNIMPLEMENTED_FEATURE; return 0; }