xref: /optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_subject_public_key_info.c (revision 8411e6ad673d20c4742ed30c785e3f5cdea54dfa)
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file x509_decode_subject_public_key_info.c
7   ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav
8 */
9 
10 #ifdef LTC_DER
11 
12 /* AlgorithmIdentifier := SEQUENCE {
13  *    algorithm OBJECT IDENTIFIER,
14  *    parameters ANY DEFINED BY algorithm
15  * }
16  *
17  * SubjectPublicKeyInfo := SEQUENCE {
18  *    algorithm AlgorithmIdentifier,
19  *    subjectPublicKey BIT STRING
20  * }
21  */
22 /**
23   Decode a SubjectPublicKeyInfo
24    @param in      The input buffer
25    @param inlen   The length of the input buffer
26    @param algorithm             One out of the enum #public_key_algorithms
27    @param public_key            The buffer for the public key
28    @param public_key_len        [in/out] The length of the public key buffer and the written length
29    @param parameters_type       The parameters' type out of the enum ltc_asn1_type
30    @param parameters            The parameters to include
31    @param parameters_len        [in/out] The number of parameters to include
32    @return CRYPT_OK on success
33 */
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)34 int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
35         unsigned int algorithm, void* public_key, unsigned long* public_key_len,
36         ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len)
37 {
38    int err;
39    unsigned long len, alg_id_num, tmplen;
40    const char* oid;
41    unsigned char *tmpbuf;
42    unsigned long  tmpoid[16];
43    unsigned long *_parameters_len;
44    ltc_asn1_list alg_id[2];
45    ltc_asn1_list subject_pubkey[2];
46 
47    LTC_ARGCHK(in    != NULL);
48    LTC_ARGCHK(inlen != 0);
49    LTC_ARGCHK(public_key_len != NULL);
50 
51    if (parameters_type != LTC_ASN1_EOL) {
52       if ((parameters == NULL) || (parameters_len == NULL)) {
53          tmplen = 0;
54          _parameters_len = &tmplen;
55       } else {
56          _parameters_len = parameters_len;
57       }
58    }
59 
60    err = pk_get_oid(algorithm, &oid);
61    if (err != CRYPT_OK) {
62         return err;
63    }
64 
65    /* see if the OpenSSL DER format RSA public key will work */
66    tmpbuf = XCALLOC(1, inlen);
67    if (tmpbuf == NULL) {
68        err = CRYPT_MEM;
69        goto LBL_ERR;
70    }
71 
72    /* this includes the internal hash ID and optional params (NULL in this case) */
73    LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0]));
74    if (parameters_type == LTC_ASN1_EOL) {
75       alg_id_num = 1;
76    } else {
77       LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, *_parameters_len);
78       alg_id_num = 2;
79    }
80 
81    /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey
82     * in a **BIT** string ... so we have to extract it then proceed to convert bit to octet
83     */
84    LTC_SET_ASN1(subject_pubkey, 0, LTC_ASN1_SEQUENCE, alg_id, alg_id_num);
85    LTC_SET_ASN1(subject_pubkey, 1, LTC_ASN1_RAW_BIT_STRING, tmpbuf, inlen*8U);
86 
87    err=der_decode_sequence(in, inlen, subject_pubkey, 2UL);
88    if (err != CRYPT_OK) {
89            goto LBL_ERR;
90    }
91    if (parameters_type != LTC_ASN1_EOL) {
92       *_parameters_len = alg_id[1].size;
93    }
94 
95    if ((err = pk_oid_cmp_with_asn1(oid, &alg_id[0])) != CRYPT_OK) {
96       /* OID mismatch */
97       goto LBL_ERR;
98    }
99 
100    len = subject_pubkey[1].size/8;
101    if (*public_key_len >= len) {
102        XMEMCPY(public_key, subject_pubkey[1].data, len);
103        *public_key_len = len;
104     } else {
105         *public_key_len = len;
106         err = CRYPT_BUFFER_OVERFLOW;
107         goto LBL_ERR;
108     }
109 
110     err = CRYPT_OK;
111 
112 LBL_ERR:
113 
114     XFREE(tmpbuf);
115 
116     return err;
117 }
118 
119 #endif
120