/
githubmirror
/
gnutls
Обзор
Документация
Войти
/
githubmirror
/
gnutls
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
lib/x509/key_decode.c
857 строк
22 KB
Daiki Ueno
pkcs8: remove HAVE_LIBOQS ifdefs
22 янв 2025, 01:38
22 янв 2025, 01:38
36eebe7
Код
Авторство
О чём код?
/* * Copyright (C) 2011-2012 Free Software Foundation, Inc. * Copyright (C) 2013-2017 Red Hat * * Author: Nikos Mavrogiannopoulos * * This file is part of GnuTLS. * * The GnuTLS is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <https://www.gnu.org/licenses/> * */ #include "gnutls_int.h" #include "errors.h" #include "global.h" #include <libtasn1.h> #include "datum.h" #include "common.h" #include "x509_int.h" #include "pk.h" #include "num.h" #include "ecc.h" static int _gnutls_x509_read_rsa_pubkey(uint8_t *der, int dersize, gnutls_pk_params_st *params); static int _gnutls_x509_read_dsa_pubkey(uint8_t *der, int dersize, gnutls_pk_params_st *params); static int _gnutls_x509_read_ecc_pubkey(uint8_t *der, int dersize, gnutls_pk_params_st *params); static int _gnutls_x509_read_eddsa_pubkey(gnutls_ecc_curve_t curve, uint8_t *der, int dersize, gnutls_pk_params_st *params); static int _gnutls_x509_read_ecdh_pubkey(gnutls_ecc_curve_t curve, uint8_t *der, int dersize, gnutls_pk_params_st *params); static int _gnutls_x509_read_gost_pubkey(uint8_t *der, int dersize, gnutls_pk_params_st *params); static int _gnutls_x509_read_dsa_params(uint8_t *der, int dersize, gnutls_pk_params_st *params); /* * some x509 certificate parsing functions that relate to MPI parameter * extraction. This reads the BIT STRING subjectPublicKey. * Returns 2 parameters (m,e). It does not set params_nr. */ int _gnutls_x509_read_rsa_pubkey(uint8_t *der, int dersize, gnutls_pk_params_st *params) { int result; asn1_node spk = NULL; if ((result = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.RSAPublicKey", &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); } if (_gnutls_x509_read_int(spk, "modulus", ¶ms->params[0]) < 0) { gnutls_assert(); asn1_delete_structure(&spk); return GNUTLS_E_ASN1_GENERIC_ERROR; } if (_gnutls_x509_read_int(spk, "publicExponent", ¶ms->params[1]) < 0) { gnutls_assert(); _gnutls_mpi_release(¶ms->params[0]); asn1_delete_structure(&spk); return GNUTLS_E_ASN1_GENERIC_ERROR; } asn1_delete_structure(&spk); return 0; } /* * some x509 certificate parsing functions that relate to MPI parameter * extraction. This reads the BIT STRING subjectPublicKey. * Returns 2 parameters (m,e). It does not set params_nr. */ int _gnutls_x509_read_ecc_pubkey(uint8_t *der, int dersize, gnutls_pk_params_st *params) { /* RFC5480 defines the public key to be an ECPoint (i.e. OCTET STRING), * Then it says that the OCTET STRING _value_ is converted to BIT STRING. * That means that the value we place there is the raw X9.62 one. */ return _gnutls_ecc_ansi_x962_import( der, dersize, ¶ms->params[ECC_X], ¶ms->params[ECC_Y]); } int _gnutls_x509_read_eddsa_pubkey(gnutls_ecc_curve_t curve, uint8_t *der, int dersize, gnutls_pk_params_st *params) { int size = gnutls_ecc_curve_get_size(curve); if (dersize != size) return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); return _gnutls_set_datum(¶ms->raw_pub, der, dersize); } int _gnutls_x509_read_ecdh_pubkey(gnutls_ecc_curve_t curve, uint8_t *der, int dersize, gnutls_pk_params_st *params) { int size = gnutls_ecc_curve_get_size(curve); if (dersize != size) return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); return _gnutls_set_datum(¶ms->raw_pub, der, dersize); } /* Pubkey is a concatenation of X (in little endian) and Y (also LE) * encoded into OCTET STRING. */ static int _gnutls_x509_read_gost_pubkey(uint8_t *der, int dersize, gnutls_pk_params_st *params) { int ret; int len; bigint_t *x = ¶ms->params[GOST_X]; bigint_t *y = ¶ms->params[GOST_Y]; /* Quick and dirty parsing of OCTET STRING of 0x40 or 0x80 bytes */ if (dersize < 1 || der[0] != ASN1_TAG_OCTET_STRING) { return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); } der++; dersize--; ret = asn1_get_length_der(der, dersize, &len); if (ret <= 0 || ret % 2 != 0 || dersize != len + ret) { return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); } der += len; dersize -= len; /* read data */ ret = _gnutls_mpi_init_scan_le(x, der, dersize / 2); if (ret < 0) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ret = _gnutls_mpi_init_scan_le(y, der + dersize / 2, dersize / 2); if (ret < 0) { _gnutls_mpi_release(y); return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); } return 0; } /* 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(uint8_t *der, int dersize, gnutls_pk_params_st *params) { int result; asn1_node spk = NULL; 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); } /* If the parameters are not included in the certificate * then the issuer's parameters should be used. This is not * implemented, and is not used in practice (along with DSA). */ /* Read p */ if (_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 (_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 (_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); params->params_nr = 3; /* public key is missing */ params->algo = GNUTLS_PK_DSA; return 0; } /* reads the curve from the certificate. * params[0-4]. It does NOT set params_nr. */ int _gnutls_x509_read_ecc_params(uint8_t *der, int dersize, unsigned int *curve) { int ret; asn1_node spk = NULL; 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 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; } *curve = gnutls_oid_to_ecc_curve(oid); if (*curve == 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 = 0; cleanup: asn1_delete_structure(&spk); return ret; } static int check_mgf1(asn1_node root, const char *name, gnutls_digest_algorithm_t digest, bool allow_null) { char buffer[MAX_NAME_SIZE]; char oid[MAX_OID_SIZE]; gnutls_digest_algorithm_t digest2; asn1_node ai = NULL; int size; int result; gnutls_datum_t value = { NULL, 0 }; result = snprintf(buffer, sizeof(buffer), "%s.algorithm", name); if (result < 0 || (size_t)result >= sizeof(buffer)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); size = sizeof(oid); result = asn1_read_value(root, buffer, oid, &size); if (result != ASN1_SUCCESS) { if (result == ASN1_ELEMENT_NOT_FOUND && allow_null) return 0; gnutls_assert(); return _gnutls_asn2err(result); } /* Error out if algorithm other than mgf1 is specified */ if (strcmp(oid, PKIX1_RSA_PSS_MGF1_OID) != 0) { gnutls_assert(); _gnutls_debug_log("Unknown mask algorithm: %s\n", oid); return gnutls_assert_val(GNUTLS_E_UNKNOWN_ALGORITHM); } /* Check if maskGenAlgorithm.parameters does exist and * is identical to hashAlgorithm */ result = snprintf(buffer, sizeof(buffer), "%s.parameters", name); if (result < 0 || (size_t)result >= sizeof(buffer)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); result = _gnutls_x509_read_value(root, buffer, &value); if (result < 0) return gnutls_assert_val(result); if ((result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.AlgorithmIdentifier", &ai)) != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } result = _asn1_strict_der_decode(&ai, value.data, value.size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } size = sizeof(oid); result = asn1_read_value(ai, "algorithm", oid, &size); if (result == ASN1_SUCCESS) digest2 = gnutls_oid_to_digest(oid); else if (result == ASN1_ELEMENT_NOT_FOUND) /* The default hash algorithm for mgf1 is SHA-1 */ digest2 = GNUTLS_DIG_SHA1; else { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (digest != digest2) { gnutls_assert(); result = GNUTLS_E_CONSTRAINT_ERROR; goto cleanup; } result = 0; cleanup: _gnutls_free_datum(&value); asn1_delete_structure(&ai); return result; } /* Reads RSA-PSS parameters. */ int _gnutls_x509_read_rsa_pss_params(uint8_t *der, int dersize, gnutls_x509_spki_st *params) { int result; asn1_node spk = NULL; gnutls_digest_algorithm_t digest; char oid[MAX_OID_SIZE] = ""; int size; unsigned int trailer; if ((result = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.RSAPSSParameters", &spk)) != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } result = _asn1_strict_der_decode(&spk, der, dersize, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } size = sizeof(oid); result = asn1_read_value(spk, "hashAlgorithm.algorithm", oid, &size); if (result == ASN1_SUCCESS) digest = gnutls_oid_to_digest(oid); else if (result == ASN1_ELEMENT_NOT_FOUND) /* The default hash algorithm is SHA-1 */ digest = GNUTLS_DIG_SHA1; else { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (digest == GNUTLS_DIG_UNKNOWN) { gnutls_assert(); _gnutls_debug_log("Unknown RSA-PSS hash: %s\n", oid); result = GNUTLS_E_UNKNOWN_HASH_ALGORITHM; goto cleanup; } result = check_mgf1(spk, "maskGenAlgorithm", digest, true); if (result < 0) { gnutls_assert(); goto cleanup; } memset(params, 0, sizeof(gnutls_x509_spki_st)); params->pk = GNUTLS_PK_RSA_PSS; params->rsa_pss_dig = digest; result = _gnutls_x509_read_uint(spk, "saltLength", ¶ms->salt_size); if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND || result == GNUTLS_E_ASN1_VALUE_NOT_FOUND) params->salt_size = 20; else if (result < 0) { gnutls_assert(); goto cleanup; } result = _gnutls_x509_read_uint(spk, "trailerField", &trailer); if (result == GNUTLS_E_ASN1_VALUE_NOT_FOUND || result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) trailer = 1; else if (result < 0) { gnutls_assert(); goto cleanup; } if (trailer != 1) { gnutls_assert(); result = GNUTLS_E_CERTIFICATE_ERROR; goto cleanup; } result = 0; cleanup: asn1_delete_structure(&spk); return result; } static int read_rsa_oaep_label(asn1_node root, const char *name, gnutls_datum_t *label, bool allow_null) { char buffer[MAX_NAME_SIZE]; char oid[MAX_OID_SIZE] = ""; int size; int result; gnutls_datum_t der = { NULL, 0 }; result = snprintf(buffer, sizeof(buffer), "%s.algorithm", name); if (result < 0 || (size_t)result >= sizeof(buffer)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); size = sizeof(oid); result = asn1_read_value(root, buffer, oid, &size); if (result != ASN1_SUCCESS) { if (result != ASN1_ELEMENT_NOT_FOUND && allow_null) return 0; gnutls_assert(); return _gnutls_asn2err(result); } /* Error out if algorithm other than mgf1 is specified */ if (strcmp(oid, PKIX1_RSA_OAEP_P_SPECIFIED_OID) != 0) { gnutls_assert(); _gnutls_debug_log("Unknown pSourceFunc algorithm: %s\n", oid); return GNUTLS_E_UNKNOWN_ALGORITHM; } /* Extract label from pSourceFunc.parameters */ result = snprintf(buffer, sizeof(buffer), "%s.parameters", name); if (result < 0 || (size_t)result >= sizeof(buffer)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); result = _gnutls_x509_read_null_value(root, buffer, &der); if (result < 0) { gnutls_assert(); goto cleanup; } result = _gnutls_x509_decode_string(ASN1_ETYPE_OCTET_STRING, der.data, der.size, label, 0); if (result < 0) { gnutls_assert(); goto cleanup; } result = 0; cleanup: _gnutls_free_datum(&der); return result; } /* Reads RSA-OAEP parameters. */ int _gnutls_x509_read_rsa_oaep_params(uint8_t *der, int dersize, gnutls_x509_spki_st *params) { int result; asn1_node spk = NULL; gnutls_digest_algorithm_t digest; char oid[MAX_OID_SIZE] = ""; int size; gnutls_datum_t label = { NULL, 0 }; if ((result = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.RSAOAEPParameters", &spk)) != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } result = _asn1_strict_der_decode(&spk, der, dersize, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } size = sizeof(oid); result = asn1_read_value(spk, "hashAlgorithm.algorithm", oid, &size); if (result == ASN1_SUCCESS) digest = gnutls_oid_to_digest(oid); else if (result == ASN1_ELEMENT_NOT_FOUND) /* The default hash algorithm is SHA-1 */ digest = GNUTLS_DIG_SHA1; else { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } if (digest == GNUTLS_DIG_UNKNOWN) { gnutls_assert(); _gnutls_debug_log("Unknown RSA-OAEP hash: %s\n", oid); result = GNUTLS_E_UNKNOWN_HASH_ALGORITHM; goto cleanup; } result = check_mgf1(spk, "maskGenAlgorithm", digest, true); if (result < 0) { gnutls_assert(); goto cleanup; } result = read_rsa_oaep_label(spk, "pSourceFunc", &label, true); if (result < 0) { gnutls_assert(); goto cleanup; } memset(params, 0, sizeof(gnutls_x509_spki_st)); params->pk = GNUTLS_PK_RSA_OAEP; params->rsa_oaep_dig = digest; if (label.data) { params->rsa_oaep_label = label; label.data = NULL; } result = 0; cleanup: _gnutls_free_datum(&label); asn1_delete_structure(&spk); return result; } /* reads the curve from the certificate. * It does NOT set params_nr. */ int _gnutls_x509_read_gost_params(uint8_t *der, int dersize, gnutls_pk_params_st *params, gnutls_pk_algorithm_t algo) { int ret; asn1_node spk = NULL; char oid[MAX_OID_SIZE]; int oid_size; gnutls_ecc_curve_t curve; gnutls_gost_paramset_t param; if ((ret = asn1_create_element(_gnutls_get_gnutls_asn(), algo == GNUTLS_PK_GOST_01 ? "GNUTLS.GOSTParametersOld" : "GNUTLS.GOSTParameters", &spk)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(ret); } ret = _asn1_strict_der_decode(&spk, der, dersize, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } /* read the curve */ oid_size = sizeof(oid); ret = asn1_read_value(spk, "publicKeyParamSet", oid, &oid_size); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } curve = gnutls_oid_to_ecc_curve(oid); if (curve == GNUTLS_ECC_CURVE_INVALID) { _gnutls_debug_log("Curve %s is not supported\n", oid); gnutls_assert(); ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE; goto cleanup; } /* Read the digest */ oid_size = sizeof(oid); ret = asn1_read_value(spk, "digestParamSet", oid, &oid_size); if (ret != ASN1_SUCCESS && ret != ASN1_ELEMENT_NOT_FOUND) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } /* For now ignore the OID: we use pk OID instead */ oid_size = sizeof(oid); ret = asn1_read_value(spk, "encryptionParamSet", oid, &oid_size); if (ret != ASN1_SUCCESS && ret != ASN1_ELEMENT_NOT_FOUND) { gnutls_assert(); ret = _gnutls_asn2err(ret); goto cleanup; } if (ret != ASN1_ELEMENT_NOT_FOUND) param = gnutls_oid_to_gost_paramset(oid); else param = _gnutls_gost_paramset_default(algo); if (param == GNUTLS_GOST_PARAMSET_UNKNOWN) { gnutls_assert(); ret = param; goto cleanup; } params->curve = curve; params->gost_params = param; ret = 0; cleanup: asn1_delete_structure(&spk); return ret; } /* This function must be called after _gnutls_x509_read_params() */ int _gnutls_x509_read_pubkey(gnutls_pk_algorithm_t algo, uint8_t *der, int dersize, gnutls_pk_params_st *params) { int ret; switch (algo) { case GNUTLS_PK_RSA: case GNUTLS_PK_RSA_PSS: case GNUTLS_PK_RSA_OAEP: ret = _gnutls_x509_read_rsa_pubkey(der, dersize, params); if (ret >= 0) { params->algo = algo; params->params_nr = RSA_PUBLIC_PARAMS; } break; case GNUTLS_PK_DSA: if (params->params_nr != 3) /* _gnutls_x509_read_pubkey_params must have been called */ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); ret = _gnutls_x509_read_dsa_pubkey(der, dersize, params); if (ret >= 0) { params->algo = GNUTLS_PK_DSA; params->params_nr = DSA_PUBLIC_PARAMS; } break; case GNUTLS_PK_ECDSA: ret = _gnutls_x509_read_ecc_pubkey(der, dersize, params); if (ret >= 0) { params->algo = GNUTLS_PK_ECDSA; params->params_nr = ECC_PUBLIC_PARAMS; } break; case GNUTLS_PK_EDDSA_ED25519: ret = _gnutls_x509_read_eddsa_pubkey(GNUTLS_ECC_CURVE_ED25519, der, dersize, params); break; case GNUTLS_PK_EDDSA_ED448: ret = _gnutls_x509_read_eddsa_pubkey(GNUTLS_ECC_CURVE_ED448, der, dersize, params); break; case GNUTLS_PK_ECDH_X25519: ret = _gnutls_x509_read_ecdh_pubkey(GNUTLS_ECC_CURVE_X25519, der, dersize, params); break; case GNUTLS_PK_ECDH_X448: ret = _gnutls_x509_read_ecdh_pubkey(GNUTLS_ECC_CURVE_X448, der, dersize, params); break; case GNUTLS_PK_GOST_01: case GNUTLS_PK_GOST_12_256: case GNUTLS_PK_GOST_12_512: ret = _gnutls_x509_read_gost_pubkey(der, dersize, params); if (ret >= 0) { params->algo = algo; params->params_nr = GOST_PUBLIC_PARAMS; } break; case GNUTLS_PK_MLDSA44: case GNUTLS_PK_MLDSA65: case GNUTLS_PK_MLDSA87: ret = _gnutls_set_datum(¶ms->raw_pub, der, dersize); break; default: ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); break; } return ret; } /* This function must be called prior to _gnutls_x509_read_pubkey() */ int _gnutls_x509_read_pubkey_params(gnutls_pk_algorithm_t algo, uint8_t *der, int dersize, gnutls_pk_params_st *params) { switch (algo) { case GNUTLS_PK_RSA: case GNUTLS_PK_EDDSA_ED25519: case GNUTLS_PK_EDDSA_ED448: return 0; case GNUTLS_PK_RSA_PSS: return _gnutls_x509_read_rsa_pss_params(der, dersize, ¶ms->spki); case GNUTLS_PK_RSA_OAEP: return _gnutls_x509_read_rsa_oaep_params(der, dersize, ¶ms->spki); case GNUTLS_PK_DSA: return _gnutls_x509_read_dsa_params(der, dersize, params); case GNUTLS_PK_EC: return _gnutls_x509_read_ecc_params(der, dersize, ¶ms->curve); case GNUTLS_PK_GOST_01: case GNUTLS_PK_GOST_12_256: case GNUTLS_PK_GOST_12_512: return _gnutls_x509_read_gost_params(der, dersize, params, algo); default: return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); } } /* This function must be called after _gnutls_x509_read_pubkey() */ int _gnutls_x509_check_pubkey_params(gnutls_pk_params_st *params) { switch (params->algo) { case GNUTLS_PK_RSA_PSS: { unsigned bits; const mac_entry_st *me; size_t hash_size; if (params->spki.pk == GNUTLS_PK_UNKNOWN) /* no params present */ return 0; bits = pubkey_to_bits(params); me = hash_to_entry(params->spki.rsa_pss_dig); if (unlikely(me == NULL)) return gnutls_assert_val( GNUTLS_E_PK_INVALID_PUBKEY_PARAMS); hash_size = _gnutls_hash_get_algo_len(me); if (hash_size + params->spki.salt_size + 2 > (bits + 7) / 8) return gnutls_assert_val( GNUTLS_E_PK_INVALID_PUBKEY_PARAMS); return 0; } case GNUTLS_PK_RSA_OAEP: { unsigned bits; const mac_entry_st *me; size_t hash_size; if (params->spki.pk == GNUTLS_PK_UNKNOWN) /* no params present */ return 0; bits = pubkey_to_bits(params); me = hash_to_entry(params->spki.rsa_oaep_dig); if (unlikely(me == NULL)) return gnutls_assert_val( GNUTLS_E_PK_INVALID_PUBKEY_PARAMS); hash_size = _gnutls_hash_get_algo_len(me); if (2 * hash_size + 2 > (bits + 7) / 8) return gnutls_assert_val( GNUTLS_E_PK_INVALID_PUBKEY_PARAMS); return 0; } case GNUTLS_PK_RSA: case GNUTLS_PK_DSA: case GNUTLS_PK_ECDSA: case GNUTLS_PK_EDDSA_ED25519: case GNUTLS_PK_EDDSA_ED448: case GNUTLS_PK_ECDH_X25519: case GNUTLS_PK_ECDH_X448: case GNUTLS_PK_GOST_01: case GNUTLS_PK_GOST_12_256: case GNUTLS_PK_GOST_12_512: case GNUTLS_PK_MLDSA44: case GNUTLS_PK_MLDSA65: case GNUTLS_PK_MLDSA87: return 0; default: return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); } } /* reads DSA's Y * from the certificate * only sets params[3] */ int _gnutls_x509_read_dsa_pubkey(uint8_t *der, int dersize, gnutls_pk_params_st *params) { return _gnutls_x509_read_der_int(der, dersize, ¶ms->params[3]); }