/* 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; }
/* 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, gnutls_pk_params_st * params) { 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); } result = _gnutls_x509_write_pubkey_params (pk_algorithm, params, &der); if (result < 0) { gnutls_assert (); return result; } _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_pubkey (pk_algorithm, params, &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); } return 0; }
/* 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; opaque *str = NULL; int algo; char oid[64]; int len; bigint_t params[MAX_PUBLIC_PARAMS_SIZE]; char name[128]; _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_x509_log ("%s: unknown public key algorithm: %s\n", __func__, oid); } if (bits == NULL) { return algo; } /* Now read the parameters' bits */ _asnstr_append_name (name, sizeof (name), src_name, ".subjectPublicKey"); len = 0; result = asn1_read_value (src, name, NULL, &len); if (result != ASN1_MEM_ERROR) { gnutls_assert (); return _gnutls_asn2err (result); } if (len % 8 != 0) { gnutls_assert (); return GNUTLS_E_CERTIFICATE_ERROR; } len /= 8; str = gnutls_malloc (len); if (str == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _asnstr_append_name (name, sizeof (name), src_name, ".subjectPublicKey"); result = asn1_read_value (src, name, str, &len); if (result != ASN1_SUCCESS) { gnutls_assert (); gnutls_free (str); return _gnutls_asn2err (result); } len /= 8; switch (algo) { case GNUTLS_PK_RSA: { if ((result = _gnutls_x509_read_rsa_params (str, len, params)) < 0) { gnutls_assert (); return result; } bits[0] = _gnutls_mpi_get_nbits (params[0]); _gnutls_mpi_release (¶ms[0]); _gnutls_mpi_release (¶ms[1]); } break; case GNUTLS_PK_DSA: { if ((result = _gnutls_x509_read_dsa_pubkey (str, len, params)) < 0) { gnutls_assert (); return result; } bits[0] = _gnutls_mpi_get_nbits (params[3]); _gnutls_mpi_release (¶ms[3]); } break; } gnutls_free (str); return algo; }
/* Extracts DSA and RSA parameters from a certificate. */ int _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root, bigint_t * params, int *params_size) { int result; char name[256]; gnutls_datum_t tmp = { NULL, 0 }; gnutls_pk_algorithm_t pk_algorithm; result = _gnutls_x509_get_pk_algorithm (asn, root, NULL); if (result < 0) { gnutls_assert (); return result; } pk_algorithm = result; /* Read the algorithm's parameters */ _asnstr_append_name (name, sizeof (name), root, ".subjectPublicKey"); result = _gnutls_x509_read_value (asn, name, &tmp, 2); if (result < 0) { gnutls_assert (); return result; } switch (pk_algorithm) { case GNUTLS_PK_RSA: /* params[0] is the modulus, * params[1] is the exponent */ if (*params_size < RSA_PUBLIC_PARAMS) { gnutls_assert (); /* internal error. Increase the bigint_ts in params */ result = GNUTLS_E_INTERNAL_ERROR; goto error; } if ((result = _gnutls_x509_read_rsa_params (tmp.data, tmp.size, params)) < 0) { gnutls_assert (); goto error; } *params_size = RSA_PUBLIC_PARAMS; break; case GNUTLS_PK_DSA: /* params[0] is p, * params[1] is q, * params[2] is q, * params[3] is pub. */ if (*params_size < DSA_PUBLIC_PARAMS) { gnutls_assert (); /* internal error. Increase the bigint_ts in params */ result = GNUTLS_E_INTERNAL_ERROR; goto error; } if ((result = _gnutls_x509_read_dsa_pubkey (tmp.data, tmp.size, params)) < 0) { gnutls_assert (); goto error; } /* Now read the parameters */ _gnutls_free_datum (&tmp); _asnstr_append_name (name, sizeof (name), root, ".algorithm.parameters"); result = _gnutls_x509_read_value (asn, name, &tmp, 0); /* FIXME: If the parameters are not included in the certificate * then the issuer's parameters should be used. This is not * done yet. */ if (result < 0) { gnutls_assert (); goto error; } if ((result = _gnutls_x509_read_dsa_params (tmp.data, tmp.size, params)) < 0) { gnutls_assert (); goto error; } *params_size = DSA_PUBLIC_PARAMS; break; default: /* other types like DH * currently not supported */ gnutls_assert (); result = GNUTLS_E_X509_CERTIFICATE_ERROR; goto error; } result = 0; error: _gnutls_free_datum (&tmp); return result; }
/* 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; }