1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3  *
4  * LibTomCrypt is a library that provides various cryptographic
5  * algorithms in a highly modular and flexible manner.
6  *
7  * The library is free for all purposes without any express
8  * guarantee it works.
9  */
10 
11 #include "tomcrypt_private.h"
12 
13 #ifdef LTC_MECC
14 
_ecc_import_private_with_oid(const unsigned char * in,unsigned long inlen,ecc_key * key)15 static int _ecc_import_private_with_oid(const unsigned char *in, unsigned long inlen, ecc_key *key)
16 {
17    ltc_asn1_list seq_priv[4], custom[2];
18    unsigned char bin_xy[2*ECC_MAXSIZE+2], bin_k[ECC_MAXSIZE];
19    unsigned long len, pkver = 0, curveoid[16];
20    char OID[256];
21    const ltc_ecc_curve *curve;
22    int err;
23 
24    /* ### try to load private key - no curve parameters just curve OID */
25 
26    /* ECPrivateKey SEQUENCE */
27    LTC_SET_ASN1(custom,   0, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL);
28    LTC_SET_ASN1(custom,   1, LTC_ASN1_RAW_BIT_STRING,    bin_xy,   8UL*sizeof(bin_xy));
29    LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER,     &pkver,   1UL);
30    LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING,      bin_k,    sizeof(bin_k));
31    LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom);     /* context specific 0 */
32    LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */
33 
34    /* try to load private key */
35    err = der_decode_sequence(in, inlen, seq_priv, 4);
36    if (err == CRYPT_OK) {
37       /* load curve parameters for given curve OID */
38       len = sizeof(OID);
39       if ((err = pk_oid_num_to_str(curveoid, custom[0].size, OID, &len)) != CRYPT_OK) { goto error; }
40       if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK)                            { goto error; }
41       if ((err = ecc_set_curve(curve, key)) != CRYPT_OK)                              { goto error; }
42       /* load private+public key */
43       err = ecc_set_key(bin_k, seq_priv[1].size, PK_PRIVATE, key);
44    }
45 error:
46    return err;
47 }
48 
_ecc_import_private_with_curve(const unsigned char * in,unsigned long inlen,ecc_key * key)49 static int _ecc_import_private_with_curve(const unsigned char *in, unsigned long inlen, ecc_key *key)
50 {
51    void *prime, *order, *a, *b, *gx, *gy;
52    ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4], custom[2];
53    unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE];
54    unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128];
55    unsigned long len_a, len_b, len_k, len_g;
56    unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16];
57    int err;
58 
59    if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) {
60       return err;
61    }
62 
63    /* ### try to load private key - curve parameters included */
64 
65    /* ECPrivateKey SEQUENCE */
66    LTC_SET_ASN1(custom,   0, LTC_ASN1_SEQUENCE,       seq_ecparams, 6UL);
67    LTC_SET_ASN1(custom,   1, LTC_ASN1_RAW_BIT_STRING, bin_xy,       8UL*sizeof(bin_xy));
68    LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER,  &pkver,       1UL);
69    LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING,   bin_k,        sizeof(bin_k));
70    LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom);     /* context specific 0 */
71    LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */
72    /* ECParameters SEQUENCE */
73    LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver,      1UL);
74    LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE,      seq_fieldid, 2UL);
75    LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE,      seq_curve,   3UL);
76    LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING,  bin_g,       sizeof(bin_g));
77    LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER,       order,       1UL);
78    LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor,   1UL);
79    seq_ecparams[5].optional = 1;
80    /* FieldID SEQUENCE */
81    LTC_SET_ASN1(seq_fieldid,  0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
82    LTC_SET_ASN1(seq_fieldid,  1, LTC_ASN1_INTEGER,           prime,  1UL);
83    /* Curve SEQUENCE */
84    LTC_SET_ASN1(seq_curve,    0, LTC_ASN1_OCTET_STRING,      bin_a,    sizeof(bin_a));
85    LTC_SET_ASN1(seq_curve,    1, LTC_ASN1_OCTET_STRING,      bin_b,    sizeof(bin_b));
86    LTC_SET_ASN1(seq_curve,    2, LTC_ASN1_RAW_BIT_STRING,    bin_seed, 8UL*sizeof(bin_seed));
87    seq_curve[2].optional = 1;
88    /* try to load private key */
89    err = der_decode_sequence(in, inlen, seq_priv, 4);
90    if (err == CRYPT_OK) {
91       len_k  = seq_priv[1].size;
92       len_a  = seq_curve[0].size;
93       len_b  = seq_curve[1].size;
94       len_g  = seq_ecparams[3].size;
95       /* create bignums */
96       if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK)                           { goto error; }
97       if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK)                           { goto error; }
98       if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK)         { goto error; }
99       /* load curve parameters */
100       if ((err = ecc_set_curve_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; }
101       /* load private+public key */
102       err = ecc_set_key(bin_k, len_k, PK_PRIVATE, key);
103    }
104 error:
105    mp_clear_multi(prime, order, a, b, gx, gy, NULL);
106    return err;
107 }
108 
ecc_import_openssl(const unsigned char * in,unsigned long inlen,ecc_key * key)109 int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key)
110 {
111    int err;
112 
113    if ((err = ecc_import_subject_public_key_info(in, inlen, key)) == CRYPT_OK) {
114       goto success;
115    }
116 
117    if ((err = _ecc_import_private_with_oid(in, inlen, key)) == CRYPT_OK) {
118       goto success;
119    }
120 
121    err = _ecc_import_private_with_curve(in, inlen, key);
122 
123 success:
124    return err;
125 }
126 
127 #endif
128 
129 /* ref:         $Format:%D$ */
130 /* git commit:  $Format:%H$ */
131 /* commit time: $Format:%ai$ */
132