// SPDX-License-Identifier: BSD-2-Clause /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. */ #include "tomcrypt_private.h" /** @file x509_decode_subject_public_key_info.c ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav */ #ifdef LTC_DER /* AlgorithmIdentifier := SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm * } * * SubjectPublicKeyInfo := SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING * } */ /** Decode a SubjectPublicKeyInfo @param in The input buffer @param inlen The length of the input buffer @param algorithm One out of the enum #public_key_algorithms @param public_key The buffer for the public key @param public_key_len [in/out] The length of the public key buffer and the written length @param parameters_type The parameters' type out of the enum ltc_asn1_type @param parameters The parameters to include @param parameters_len [in/out] The number of parameters to include @return CRYPT_OK on success */ int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen, unsigned int algorithm, void* public_key, unsigned long* public_key_len, ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len) { int err; unsigned long len, alg_id_num, tmplen; const char* oid; unsigned char *tmpbuf; unsigned long tmpoid[16]; unsigned long *_parameters_len; ltc_asn1_list alg_id[2]; ltc_asn1_list subject_pubkey[2]; LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen != 0); LTC_ARGCHK(public_key_len != NULL); if (parameters_type != LTC_ASN1_EOL) { if ((parameters == NULL) || (parameters_len == NULL)) { tmplen = 0; _parameters_len = &tmplen; } else { _parameters_len = parameters_len; } } err = pk_get_oid(algorithm, &oid); if (err != CRYPT_OK) { return err; } /* see if the OpenSSL DER format RSA public key will work */ tmpbuf = XCALLOC(1, inlen); if (tmpbuf == NULL) { err = CRYPT_MEM; goto LBL_ERR; } /* this includes the internal hash ID and optional params (NULL in this case) */ LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0])); if (parameters_type == LTC_ASN1_EOL) { alg_id_num = 1; } else { LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, *_parameters_len); alg_id_num = 2; } /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey * in a **BIT** string ... so we have to extract it then proceed to convert bit to octet */ LTC_SET_ASN1(subject_pubkey, 0, LTC_ASN1_SEQUENCE, alg_id, alg_id_num); LTC_SET_ASN1(subject_pubkey, 1, LTC_ASN1_RAW_BIT_STRING, tmpbuf, inlen*8U); err=der_decode_sequence(in, inlen, subject_pubkey, 2UL); if (err != CRYPT_OK) { goto LBL_ERR; } if (parameters_type != LTC_ASN1_EOL) { *_parameters_len = alg_id[1].size; } if ((err = pk_oid_cmp_with_asn1(oid, &alg_id[0])) != CRYPT_OK) { /* OID mismatch */ goto LBL_ERR; } len = subject_pubkey[1].size/8; if (*public_key_len >= len) { XMEMCPY(public_key, subject_pubkey[1].data, len); *public_key_len = len; } else { *public_key_len = len; err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } err = CRYPT_OK; LBL_ERR: XFREE(tmpbuf); return err; } #endif /* ref: $Format:%D$ */ /* git commit: $Format:%H$ */ /* commit time: $Format:%ai$ */