1 /*
2  *  t_cose_make_openssl_test_key.c
3  *
4  * Copyright 2019-2020, Laurence Lundblade
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * See BSD-3-Clause license in README.md
9  */
10 
11 #include "t_cose_make_test_pub_key.h" /* The interface implemented here */
12 
13 #include "openssl/ecdsa.h"
14 #include "openssl/obj_mac.h" /* for NID for EC curve */
15 #include "openssl/err.h"
16 
17 
18 /*
19  * Some hard coded keys for the test cases here.
20  */
21 #define PUBLIC_KEY_prime256v1 \
22     "0437ab65955fae0466673c3a2934a3" \
23     "4f2f0ec2b3eec224198557998fc04b" \
24     "f4b2b495d9798f2539c90d7d102b3b" \
25     "bbda7fcbdb0e9b58d4e1ad2e61508d" \
26     "a75f84a67b"
27 
28 #define PRIVATE_KEY_prime256v1 \
29     "f1b7142343402f3b5de7315ea894f9" \
30     "da5cf503ff7938a37ca14eb0328698" \
31     "8450"
32 
33 
34 #define PUBLIC_KEY_secp384r1 \
35     "04bdd9c3f818c9cef3e11e2d40e775" \
36     "beb37bc376698d71967f93337a4e03" \
37     "2dffb11b505067dddb4214b56d9bce" \
38     "c59177eccd8ab05f50975933b9a738" \
39     "d90c0b07eb9519567ef9075807cf77" \
40     "139fc1fe85608851361136806123ed" \
41     "c735ce5a03e8e4"
42 
43 #define PRIVATE_KEY_secp384r1 \
44     "03df14f4b8a43fd8ab75a6046bd2b5" \
45     "eaa6fd10b2b203fd8a78d7916de20a" \
46     "a241eb37ec3d4c693d23ba2b4f6e5b" \
47     "66f57f"
48 
49 
50 #define PUBLIC_KEY_secp521r1 \
51     "0400e4d253175a14311fc2dd487687" \
52     "70cb49b07bd15d327beb98aa33e60c" \
53     "d0181b17fb8f1cbf07dbc8652ff5b7" \
54     "b4452c082e0686c0fab8089071cbc5" \
55     "37101d344b94c201e6424f3a18da4f" \
56     "20ecabfbc84b8467c217cd67055fa5" \
57     "dec7fb1ae87082302c1813caa4b7b1" \
58     "cf28d94677e486fb4b317097e9307a" \
59     "bdb9d50187779a3d1e682c123c"
60 
61 #define PRIVATE_KEY_secp521r1 \
62     "0045d2d1439435fab333b1c6c8b534" \
63     "f0969396ad64d5f535d65f68f2a160" \
64     "6590bb15fd5322fc97a416c395745e" \
65     "72c7c85198c0921ab3b8e92dd901b5" \
66     "a42159adac6d"
67 
68 /*
69  * Public function, see t_cose_make_test_pub_key.h
70  */
71 /*
72  * The key object returned by this is malloced and has to be freed by
73  * by calling free_ecdsa_key_pair(). This heap use is a part of
74  * OpenSSL and not t_cose which does not use the heap
75  */
make_ecdsa_key_pair(int32_t cose_algorithm_id,struct t_cose_key * key_pair)76 enum t_cose_err_t make_ecdsa_key_pair(int32_t           cose_algorithm_id,
77                                       struct t_cose_key *key_pair)
78 {
79     EC_GROUP          *ossl_ec_group = NULL;
80     enum t_cose_err_t  return_value;
81     BIGNUM            *ossl_private_key_bn = NULL;
82     EC_KEY            *ossl_ec_key = NULL;
83     int                ossl_result;
84     EC_POINT          *ossl_pub_key_point = NULL;
85     int                nid;
86     const char        *public_key;
87     const char        *private_key;
88 
89     switch (cose_algorithm_id) {
90     case T_COSE_ALGORITHM_ES256:
91         nid         = NID_X9_62_prime256v1;
92         public_key  = PUBLIC_KEY_prime256v1;
93         private_key =  PRIVATE_KEY_prime256v1 ;
94         break;
95 
96     case T_COSE_ALGORITHM_ES384:
97         nid         = NID_secp384r1;
98         public_key  = PUBLIC_KEY_secp384r1;
99         private_key = PRIVATE_KEY_secp384r1;
100         break;
101 
102     case T_COSE_ALGORITHM_ES512:
103         nid         = NID_secp521r1;
104         public_key  = PUBLIC_KEY_secp521r1;
105         private_key = PRIVATE_KEY_secp521r1;
106         break;
107 
108     default:
109         return -1;
110     }
111 
112     /* Make a group for the particular EC algorithm */
113     ossl_ec_group = EC_GROUP_new_by_curve_name(nid);
114     if(ossl_ec_group == NULL) {
115         return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
116         goto Done;
117     }
118 
119     /* Make an empty EC key object */
120     ossl_ec_key = EC_KEY_new();
121     if(ossl_ec_key == NULL) {
122         return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
123         goto Done;
124     }
125 
126     /* Associate group with key object */
127     ossl_result = EC_KEY_set_group(ossl_ec_key, ossl_ec_group);
128     if (!ossl_result) {
129         return_value = T_COSE_ERR_SIG_FAIL;
130         goto Done;
131     }
132 
133     /* Make an instance of a big number to store the private key */
134     ossl_private_key_bn = BN_new();
135     if(ossl_private_key_bn == NULL) {
136         return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
137         goto Done;
138     }
139     BN_zero(ossl_private_key_bn);
140 
141     /* Stuff the specific private key into the big num */
142     ossl_result = BN_hex2bn(&ossl_private_key_bn, private_key);
143     if(ossl_private_key_bn == 0) {
144         return_value = T_COSE_ERR_SIG_FAIL;
145         goto Done;
146     }
147 
148     /* Now associate the big num with the key object so we finally
149      * have a key set up and ready for signing */
150     ossl_result = EC_KEY_set_private_key(ossl_ec_key, ossl_private_key_bn);
151     if (!ossl_result) {
152         return_value = T_COSE_ERR_SIG_FAIL;
153         goto Done;
154     }
155 
156 
157     /* Make an empty EC point into which the public key gets loaded */
158     ossl_pub_key_point = EC_POINT_new(ossl_ec_group);
159     if(ossl_pub_key_point == NULL) {
160         return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
161         goto Done;
162     }
163 
164     /* Turn the serialized public key into an EC point */
165     ossl_pub_key_point = EC_POINT_hex2point(ossl_ec_group,
166                                             public_key,
167                                             ossl_pub_key_point,
168                                             NULL);
169     if(ossl_pub_key_point == NULL) {
170         return_value = T_COSE_ERR_SIG_FAIL;
171         goto Done;
172     }
173 
174     /* Associate the EC point with key object */
175     /* The key object has both the public and private keys in it */
176     ossl_result = EC_KEY_set_public_key(ossl_ec_key, ossl_pub_key_point);
177     if(ossl_result == 0) {
178         return_value = T_COSE_ERR_SIG_FAIL;
179         goto Done;
180     }
181 
182     key_pair->k.key_ptr  = ossl_ec_key;
183     key_pair->crypto_lib = T_COSE_CRYPTO_LIB_OPENSSL;
184     return_value         = T_COSE_SUCCESS;
185 
186 Done:
187     return return_value;
188 }
189 
190 
191 /*
192  * Public function, see t_cose_make_test_pub_key.h
193  */
free_ecdsa_key_pair(struct t_cose_key key_pair)194 void free_ecdsa_key_pair(struct t_cose_key key_pair)
195 {
196     EC_KEY_free(key_pair.k.key_ptr);
197 }
198 
199 
200 /*
201  * Public function, see t_cose_make_test_pub_key.h
202  */
check_for_key_pair_leaks()203 int check_for_key_pair_leaks()
204 {
205     /* So far no good way to do this for OpenSSL or malloc() in general
206        in a nice portable way. The PSA version does check so there is
207        some coverage of the code even though there is no check here.
208      */
209     return 0;
210 }
211 
212 
213 
214