119c402afSSimon Glass /*
219c402afSSimon Glass * Copyright (c) 2013, Google Inc.
319c402afSSimon Glass *
41a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
519c402afSSimon Glass */
619c402afSSimon Glass
719c402afSSimon Glass #include "mkimage.h"
819c402afSSimon Glass #include <stdio.h>
919c402afSSimon Glass #include <string.h>
1019c402afSSimon Glass #include <image.h>
1119c402afSSimon Glass #include <time.h>
12781ee9b3SJason Zhu #include <generated/autoconf.h>
13c3b43281SJelle van der Waa #include <openssl/bn.h>
1419c402afSSimon Glass #include <openssl/rsa.h>
1519c402afSSimon Glass #include <openssl/pem.h>
1619c402afSSimon Glass #include <openssl/err.h>
1719c402afSSimon Glass #include <openssl/ssl.h>
1819c402afSSimon Glass #include <openssl/evp.h>
19f1ca1fdeSGeorge McCollister #include <openssl/engine.h>
2019c402afSSimon Glass
2119c402afSSimon Glass #if OPENSSL_VERSION_NUMBER >= 0x10000000L
2219c402afSSimon Glass #define HAVE_ERR_REMOVE_THREAD_STATE
2319c402afSSimon Glass #endif
2419c402afSSimon Glass
25c3b43281SJelle van der Waa #if OPENSSL_VERSION_NUMBER < 0x10100000L
RSA_get0_key(const RSA * r,const BIGNUM ** n,const BIGNUM ** e,const BIGNUM ** d)26c3b43281SJelle van der Waa static void RSA_get0_key(const RSA *r,
27c3b43281SJelle van der Waa const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
28c3b43281SJelle van der Waa {
29c3b43281SJelle van der Waa if (n != NULL)
30c3b43281SJelle van der Waa *n = r->n;
31c3b43281SJelle van der Waa if (e != NULL)
32c3b43281SJelle van der Waa *e = r->e;
33c3b43281SJelle van der Waa if (d != NULL)
34c3b43281SJelle van der Waa *d = r->d;
35c3b43281SJelle van der Waa }
36c3b43281SJelle van der Waa #endif
37c3b43281SJelle van der Waa
rsa_err(const char * msg)3819c402afSSimon Glass static int rsa_err(const char *msg)
3919c402afSSimon Glass {
4019c402afSSimon Glass unsigned long sslErr = ERR_get_error();
4119c402afSSimon Glass
4219c402afSSimon Glass fprintf(stderr, "%s", msg);
4319c402afSSimon Glass fprintf(stderr, ": %s\n",
4419c402afSSimon Glass ERR_error_string(sslErr, 0));
4519c402afSSimon Glass
4619c402afSSimon Glass return -1;
4719c402afSSimon Glass }
4819c402afSSimon Glass
4919c402afSSimon Glass /**
50f1ca1fdeSGeorge McCollister * rsa_pem_get_pub_key() - read a public key from a .crt file
5119c402afSSimon Glass *
5219c402afSSimon Glass * @keydir: Directory containins the key
5319c402afSSimon Glass * @name Name of key file (will have a .crt extension)
5419c402afSSimon Glass * @rsap Returns RSA object, or NULL on failure
5519c402afSSimon Glass * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
5619c402afSSimon Glass */
rsa_pem_get_pub_key(const char * keydir,const char * name,RSA ** rsap)57f1ca1fdeSGeorge McCollister static int rsa_pem_get_pub_key(const char *keydir, const char *name, RSA **rsap)
5819c402afSSimon Glass {
5919c402afSSimon Glass char path[1024];
6019c402afSSimon Glass EVP_PKEY *key;
6119c402afSSimon Glass X509 *cert;
6219c402afSSimon Glass RSA *rsa;
6319c402afSSimon Glass FILE *f;
6419c402afSSimon Glass int ret;
6519c402afSSimon Glass
6619c402afSSimon Glass *rsap = NULL;
6719c402afSSimon Glass snprintf(path, sizeof(path), "%s/%s.crt", keydir, name);
6819c402afSSimon Glass f = fopen(path, "r");
6919c402afSSimon Glass if (!f) {
7019c402afSSimon Glass fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n",
7119c402afSSimon Glass path, strerror(errno));
7219c402afSSimon Glass return -EACCES;
7319c402afSSimon Glass }
7419c402afSSimon Glass
7519c402afSSimon Glass /* Read the certificate */
7619c402afSSimon Glass cert = NULL;
7719c402afSSimon Glass if (!PEM_read_X509(f, &cert, NULL, NULL)) {
7819c402afSSimon Glass rsa_err("Couldn't read certificate");
7919c402afSSimon Glass ret = -EINVAL;
8019c402afSSimon Glass goto err_cert;
8119c402afSSimon Glass }
8219c402afSSimon Glass
8319c402afSSimon Glass /* Get the public key from the certificate. */
8419c402afSSimon Glass key = X509_get_pubkey(cert);
8519c402afSSimon Glass if (!key) {
8619c402afSSimon Glass rsa_err("Couldn't read public key\n");
8719c402afSSimon Glass ret = -EINVAL;
8819c402afSSimon Glass goto err_pubkey;
8919c402afSSimon Glass }
9019c402afSSimon Glass
9119c402afSSimon Glass /* Convert to a RSA_style key. */
9219c402afSSimon Glass rsa = EVP_PKEY_get1_RSA(key);
9319c402afSSimon Glass if (!rsa) {
9419c402afSSimon Glass rsa_err("Couldn't convert to a RSA style key");
9554267162SSimon Glass ret = -EINVAL;
9619c402afSSimon Glass goto err_rsa;
9719c402afSSimon Glass }
9819c402afSSimon Glass fclose(f);
9919c402afSSimon Glass EVP_PKEY_free(key);
10019c402afSSimon Glass X509_free(cert);
10119c402afSSimon Glass *rsap = rsa;
10219c402afSSimon Glass
10319c402afSSimon Glass return 0;
10419c402afSSimon Glass
10519c402afSSimon Glass err_rsa:
10619c402afSSimon Glass EVP_PKEY_free(key);
10719c402afSSimon Glass err_pubkey:
10819c402afSSimon Glass X509_free(cert);
10919c402afSSimon Glass err_cert:
11019c402afSSimon Glass fclose(f);
11119c402afSSimon Glass return ret;
11219c402afSSimon Glass }
11319c402afSSimon Glass
11419c402afSSimon Glass /**
115f1ca1fdeSGeorge McCollister * rsa_engine_get_pub_key() - read a public key from given engine
11619c402afSSimon Glass *
117f1ca1fdeSGeorge McCollister * @keydir: Key prefix
118f1ca1fdeSGeorge McCollister * @name Name of key
119f1ca1fdeSGeorge McCollister * @engine Engine to use
120f1ca1fdeSGeorge McCollister * @rsap Returns RSA object, or NULL on failure
121f1ca1fdeSGeorge McCollister * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
122f1ca1fdeSGeorge McCollister */
rsa_engine_get_pub_key(const char * keydir,const char * name,ENGINE * engine,RSA ** rsap)123f1ca1fdeSGeorge McCollister static int rsa_engine_get_pub_key(const char *keydir, const char *name,
124f1ca1fdeSGeorge McCollister ENGINE *engine, RSA **rsap)
125f1ca1fdeSGeorge McCollister {
126f1ca1fdeSGeorge McCollister const char *engine_id;
127f1ca1fdeSGeorge McCollister char key_id[1024];
128f1ca1fdeSGeorge McCollister EVP_PKEY *key;
129f1ca1fdeSGeorge McCollister RSA *rsa;
130f1ca1fdeSGeorge McCollister int ret;
131f1ca1fdeSGeorge McCollister
132f1ca1fdeSGeorge McCollister *rsap = NULL;
133f1ca1fdeSGeorge McCollister
134f1ca1fdeSGeorge McCollister engine_id = ENGINE_get_id(engine);
135f1ca1fdeSGeorge McCollister
136f1ca1fdeSGeorge McCollister if (engine_id && !strcmp(engine_id, "pkcs11")) {
137f1ca1fdeSGeorge McCollister if (keydir)
138f1ca1fdeSGeorge McCollister snprintf(key_id, sizeof(key_id),
139f1ca1fdeSGeorge McCollister "pkcs11:%s;object=%s;type=public",
140f1ca1fdeSGeorge McCollister keydir, name);
141f1ca1fdeSGeorge McCollister else
142f1ca1fdeSGeorge McCollister snprintf(key_id, sizeof(key_id),
143f1ca1fdeSGeorge McCollister "pkcs11:object=%s;type=public",
144f1ca1fdeSGeorge McCollister name);
145f1ca1fdeSGeorge McCollister } else {
146f1ca1fdeSGeorge McCollister fprintf(stderr, "Engine not supported\n");
147f1ca1fdeSGeorge McCollister return -ENOTSUP;
148f1ca1fdeSGeorge McCollister }
149f1ca1fdeSGeorge McCollister
150f1ca1fdeSGeorge McCollister key = ENGINE_load_public_key(engine, key_id, NULL, NULL);
151f1ca1fdeSGeorge McCollister if (!key)
152f1ca1fdeSGeorge McCollister return rsa_err("Failure loading public key from engine");
153f1ca1fdeSGeorge McCollister
154f1ca1fdeSGeorge McCollister /* Convert to a RSA_style key. */
155f1ca1fdeSGeorge McCollister rsa = EVP_PKEY_get1_RSA(key);
156f1ca1fdeSGeorge McCollister if (!rsa) {
157f1ca1fdeSGeorge McCollister rsa_err("Couldn't convert to a RSA style key");
158f1ca1fdeSGeorge McCollister ret = -EINVAL;
159f1ca1fdeSGeorge McCollister goto err_rsa;
160f1ca1fdeSGeorge McCollister }
161f1ca1fdeSGeorge McCollister
162f1ca1fdeSGeorge McCollister EVP_PKEY_free(key);
163f1ca1fdeSGeorge McCollister *rsap = rsa;
164f1ca1fdeSGeorge McCollister
165f1ca1fdeSGeorge McCollister return 0;
166f1ca1fdeSGeorge McCollister
167f1ca1fdeSGeorge McCollister err_rsa:
168f1ca1fdeSGeorge McCollister EVP_PKEY_free(key);
169f1ca1fdeSGeorge McCollister return ret;
170f1ca1fdeSGeorge McCollister }
171f1ca1fdeSGeorge McCollister
172f1ca1fdeSGeorge McCollister /**
173f1ca1fdeSGeorge McCollister * rsa_get_pub_key() - read a public key
174f1ca1fdeSGeorge McCollister *
175f1ca1fdeSGeorge McCollister * @keydir: Directory containing the key (PEM file) or key prefix (engine)
176f1ca1fdeSGeorge McCollister * @name Name of key file (will have a .crt extension)
177f1ca1fdeSGeorge McCollister * @engine Engine to use
178f1ca1fdeSGeorge McCollister * @rsap Returns RSA object, or NULL on failure
179f1ca1fdeSGeorge McCollister * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
180f1ca1fdeSGeorge McCollister */
rsa_get_pub_key(const char * keydir,const char * name,ENGINE * engine,RSA ** rsap)181f1ca1fdeSGeorge McCollister static int rsa_get_pub_key(const char *keydir, const char *name,
182f1ca1fdeSGeorge McCollister ENGINE *engine, RSA **rsap)
183f1ca1fdeSGeorge McCollister {
184f1ca1fdeSGeorge McCollister if (engine)
185f1ca1fdeSGeorge McCollister return rsa_engine_get_pub_key(keydir, name, engine, rsap);
186f1ca1fdeSGeorge McCollister return rsa_pem_get_pub_key(keydir, name, rsap);
187f1ca1fdeSGeorge McCollister }
188f1ca1fdeSGeorge McCollister
189f1ca1fdeSGeorge McCollister /**
190f1ca1fdeSGeorge McCollister * rsa_pem_get_priv_key() - read a private key from a .key file
191f1ca1fdeSGeorge McCollister *
192f1ca1fdeSGeorge McCollister * @keydir: Directory containing the key
19319c402afSSimon Glass * @name Name of key file (will have a .key extension)
19419c402afSSimon Glass * @rsap Returns RSA object, or NULL on failure
19519c402afSSimon Glass * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
19619c402afSSimon Glass */
rsa_pem_get_priv_key(const char * keydir,const char * name,RSA ** rsap)197f1ca1fdeSGeorge McCollister static int rsa_pem_get_priv_key(const char *keydir, const char *name,
198f1ca1fdeSGeorge McCollister RSA **rsap)
19919c402afSSimon Glass {
20019c402afSSimon Glass char path[1024];
20119c402afSSimon Glass RSA *rsa;
20219c402afSSimon Glass FILE *f;
20319c402afSSimon Glass
20419c402afSSimon Glass *rsap = NULL;
20519c402afSSimon Glass snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
20619c402afSSimon Glass f = fopen(path, "r");
20719c402afSSimon Glass if (!f) {
20819c402afSSimon Glass fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
20919c402afSSimon Glass path, strerror(errno));
21019c402afSSimon Glass return -ENOENT;
21119c402afSSimon Glass }
21219c402afSSimon Glass
21319c402afSSimon Glass rsa = PEM_read_RSAPrivateKey(f, 0, NULL, path);
21419c402afSSimon Glass if (!rsa) {
21519c402afSSimon Glass rsa_err("Failure reading private key");
21619c402afSSimon Glass fclose(f);
21719c402afSSimon Glass return -EPROTO;
21819c402afSSimon Glass }
21919c402afSSimon Glass fclose(f);
22019c402afSSimon Glass *rsap = rsa;
22119c402afSSimon Glass
22219c402afSSimon Glass return 0;
22319c402afSSimon Glass }
22419c402afSSimon Glass
225f1ca1fdeSGeorge McCollister /**
226f1ca1fdeSGeorge McCollister * rsa_engine_get_priv_key() - read a private key from given engine
227f1ca1fdeSGeorge McCollister *
228f1ca1fdeSGeorge McCollister * @keydir: Key prefix
229f1ca1fdeSGeorge McCollister * @name Name of key
230f1ca1fdeSGeorge McCollister * @engine Engine to use
231f1ca1fdeSGeorge McCollister * @rsap Returns RSA object, or NULL on failure
232f1ca1fdeSGeorge McCollister * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
233f1ca1fdeSGeorge McCollister */
rsa_engine_get_priv_key(const char * keydir,const char * name,ENGINE * engine,RSA ** rsap)234f1ca1fdeSGeorge McCollister static int rsa_engine_get_priv_key(const char *keydir, const char *name,
235f1ca1fdeSGeorge McCollister ENGINE *engine, RSA **rsap)
236f1ca1fdeSGeorge McCollister {
237f1ca1fdeSGeorge McCollister const char *engine_id;
238f1ca1fdeSGeorge McCollister char key_id[1024];
239f1ca1fdeSGeorge McCollister EVP_PKEY *key;
240f1ca1fdeSGeorge McCollister RSA *rsa;
241f1ca1fdeSGeorge McCollister int ret;
242f1ca1fdeSGeorge McCollister
243f1ca1fdeSGeorge McCollister *rsap = NULL;
244f1ca1fdeSGeorge McCollister
245f1ca1fdeSGeorge McCollister engine_id = ENGINE_get_id(engine);
246f1ca1fdeSGeorge McCollister
247f1ca1fdeSGeorge McCollister if (engine_id && !strcmp(engine_id, "pkcs11")) {
248f1ca1fdeSGeorge McCollister if (keydir)
249f1ca1fdeSGeorge McCollister snprintf(key_id, sizeof(key_id),
250f1ca1fdeSGeorge McCollister "pkcs11:%s;object=%s;type=private",
251f1ca1fdeSGeorge McCollister keydir, name);
252f1ca1fdeSGeorge McCollister else
253f1ca1fdeSGeorge McCollister snprintf(key_id, sizeof(key_id),
254f1ca1fdeSGeorge McCollister "pkcs11:object=%s;type=private",
255f1ca1fdeSGeorge McCollister name);
256f1ca1fdeSGeorge McCollister } else {
257f1ca1fdeSGeorge McCollister fprintf(stderr, "Engine not supported\n");
258f1ca1fdeSGeorge McCollister return -ENOTSUP;
259f1ca1fdeSGeorge McCollister }
260f1ca1fdeSGeorge McCollister
261f1ca1fdeSGeorge McCollister key = ENGINE_load_private_key(engine, key_id, NULL, NULL);
262f1ca1fdeSGeorge McCollister if (!key)
263f1ca1fdeSGeorge McCollister return rsa_err("Failure loading private key from engine");
264f1ca1fdeSGeorge McCollister
265f1ca1fdeSGeorge McCollister /* Convert to a RSA_style key. */
266f1ca1fdeSGeorge McCollister rsa = EVP_PKEY_get1_RSA(key);
267f1ca1fdeSGeorge McCollister if (!rsa) {
268f1ca1fdeSGeorge McCollister rsa_err("Couldn't convert to a RSA style key");
269f1ca1fdeSGeorge McCollister ret = -EINVAL;
270f1ca1fdeSGeorge McCollister goto err_rsa;
271f1ca1fdeSGeorge McCollister }
272f1ca1fdeSGeorge McCollister
273f1ca1fdeSGeorge McCollister EVP_PKEY_free(key);
274f1ca1fdeSGeorge McCollister *rsap = rsa;
275f1ca1fdeSGeorge McCollister
276f1ca1fdeSGeorge McCollister return 0;
277f1ca1fdeSGeorge McCollister
278f1ca1fdeSGeorge McCollister err_rsa:
279f1ca1fdeSGeorge McCollister EVP_PKEY_free(key);
280f1ca1fdeSGeorge McCollister return ret;
281f1ca1fdeSGeorge McCollister }
282f1ca1fdeSGeorge McCollister
283f1ca1fdeSGeorge McCollister /**
284f1ca1fdeSGeorge McCollister * rsa_get_priv_key() - read a private key
285f1ca1fdeSGeorge McCollister *
286f1ca1fdeSGeorge McCollister * @keydir: Directory containing the key (PEM file) or key prefix (engine)
287f1ca1fdeSGeorge McCollister * @name Name of key
288f1ca1fdeSGeorge McCollister * @engine Engine to use for signing
289f1ca1fdeSGeorge McCollister * @rsap Returns RSA object, or NULL on failure
290f1ca1fdeSGeorge McCollister * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
291f1ca1fdeSGeorge McCollister */
rsa_get_priv_key(const char * keydir,const char * name,ENGINE * engine,RSA ** rsap)292f1ca1fdeSGeorge McCollister static int rsa_get_priv_key(const char *keydir, const char *name,
293f1ca1fdeSGeorge McCollister ENGINE *engine, RSA **rsap)
294f1ca1fdeSGeorge McCollister {
295f1ca1fdeSGeorge McCollister if (engine)
296f1ca1fdeSGeorge McCollister return rsa_engine_get_priv_key(keydir, name, engine, rsap);
297f1ca1fdeSGeorge McCollister return rsa_pem_get_priv_key(keydir, name, rsap);
298f1ca1fdeSGeorge McCollister }
299f1ca1fdeSGeorge McCollister
rsa_init(void)30019c402afSSimon Glass static int rsa_init(void)
30119c402afSSimon Glass {
30219c402afSSimon Glass int ret;
30319c402afSSimon Glass
304c3b43281SJelle van der Waa #if OPENSSL_VERSION_NUMBER < 0x10100000L
30519c402afSSimon Glass ret = SSL_library_init();
306c3b43281SJelle van der Waa #else
307c3b43281SJelle van der Waa ret = OPENSSL_init_ssl(0, NULL);
308c3b43281SJelle van der Waa #endif
30919c402afSSimon Glass if (!ret) {
31019c402afSSimon Glass fprintf(stderr, "Failure to init SSL library\n");
31119c402afSSimon Glass return -1;
31219c402afSSimon Glass }
313c3b43281SJelle van der Waa #if OPENSSL_VERSION_NUMBER < 0x10100000L
31419c402afSSimon Glass SSL_load_error_strings();
31519c402afSSimon Glass
31619c402afSSimon Glass OpenSSL_add_all_algorithms();
31719c402afSSimon Glass OpenSSL_add_all_digests();
31819c402afSSimon Glass OpenSSL_add_all_ciphers();
319c3b43281SJelle van der Waa #endif
32019c402afSSimon Glass
32119c402afSSimon Glass return 0;
32219c402afSSimon Glass }
32319c402afSSimon Glass
rsa_engine_init(const char * engine_id,ENGINE ** pe)324f1ca1fdeSGeorge McCollister static int rsa_engine_init(const char *engine_id, ENGINE **pe)
325f1ca1fdeSGeorge McCollister {
326f1ca1fdeSGeorge McCollister ENGINE *e;
327f1ca1fdeSGeorge McCollister int ret;
328f1ca1fdeSGeorge McCollister
329f1ca1fdeSGeorge McCollister ENGINE_load_builtin_engines();
330f1ca1fdeSGeorge McCollister
331f1ca1fdeSGeorge McCollister e = ENGINE_by_id(engine_id);
332f1ca1fdeSGeorge McCollister if (!e) {
333f1ca1fdeSGeorge McCollister fprintf(stderr, "Engine isn't available\n");
334f1ca1fdeSGeorge McCollister ret = -1;
335f1ca1fdeSGeorge McCollister goto err_engine_by_id;
336f1ca1fdeSGeorge McCollister }
337f1ca1fdeSGeorge McCollister
338f1ca1fdeSGeorge McCollister if (!ENGINE_init(e)) {
339f1ca1fdeSGeorge McCollister fprintf(stderr, "Couldn't initialize engine\n");
340f1ca1fdeSGeorge McCollister ret = -1;
341f1ca1fdeSGeorge McCollister goto err_engine_init;
342f1ca1fdeSGeorge McCollister }
343f1ca1fdeSGeorge McCollister
344f1ca1fdeSGeorge McCollister if (!ENGINE_set_default_RSA(e)) {
345f1ca1fdeSGeorge McCollister fprintf(stderr, "Couldn't set engine as default for RSA\n");
346f1ca1fdeSGeorge McCollister ret = -1;
347f1ca1fdeSGeorge McCollister goto err_set_rsa;
348f1ca1fdeSGeorge McCollister }
349f1ca1fdeSGeorge McCollister
350f1ca1fdeSGeorge McCollister *pe = e;
351f1ca1fdeSGeorge McCollister
352f1ca1fdeSGeorge McCollister return 0;
353f1ca1fdeSGeorge McCollister
354f1ca1fdeSGeorge McCollister err_set_rsa:
355f1ca1fdeSGeorge McCollister ENGINE_finish(e);
356f1ca1fdeSGeorge McCollister err_engine_init:
357f1ca1fdeSGeorge McCollister ENGINE_free(e);
358f1ca1fdeSGeorge McCollister err_engine_by_id:
359c3b43281SJelle van der Waa #if OPENSSL_VERSION_NUMBER < 0x10100000L
360f1ca1fdeSGeorge McCollister ENGINE_cleanup();
361c3b43281SJelle van der Waa #endif
362f1ca1fdeSGeorge McCollister return ret;
363f1ca1fdeSGeorge McCollister }
364f1ca1fdeSGeorge McCollister
rsa_remove(void)36519c402afSSimon Glass static void rsa_remove(void)
36619c402afSSimon Glass {
367c3b43281SJelle van der Waa #if OPENSSL_VERSION_NUMBER < 0x10100000L
36819c402afSSimon Glass CRYPTO_cleanup_all_ex_data();
36919c402afSSimon Glass ERR_free_strings();
37019c402afSSimon Glass #ifdef HAVE_ERR_REMOVE_THREAD_STATE
37119c402afSSimon Glass ERR_remove_thread_state(NULL);
37219c402afSSimon Glass #else
37319c402afSSimon Glass ERR_remove_state(0);
37419c402afSSimon Glass #endif
37519c402afSSimon Glass EVP_cleanup();
376c3b43281SJelle van der Waa #endif
37719c402afSSimon Glass }
37819c402afSSimon Glass
rsa_engine_remove(ENGINE * e)379f1ca1fdeSGeorge McCollister static void rsa_engine_remove(ENGINE *e)
380f1ca1fdeSGeorge McCollister {
381f1ca1fdeSGeorge McCollister if (e) {
382f1ca1fdeSGeorge McCollister ENGINE_finish(e);
383f1ca1fdeSGeorge McCollister ENGINE_free(e);
384f1ca1fdeSGeorge McCollister }
385f1ca1fdeSGeorge McCollister }
386f1ca1fdeSGeorge McCollister
387d46373c1SJoseph Chen /*
388d46373c1SJoseph Chen * With this data2sign.bin, we can provide it to who real holds the RAS-private
389d46373c1SJoseph Chen * key to sign current fit image. Then we replace the signature in fit image
390d46373c1SJoseph Chen * with a valid one.
391d46373c1SJoseph Chen */
gen_data2sign(const struct image_region region[],int region_count)392242e56faSJoseph Chen static int gen_data2sign(const struct image_region region[], int region_count)
393d46373c1SJoseph Chen {
394d46373c1SJoseph Chen char *file = "data2sign.bin";
395d46373c1SJoseph Chen FILE *fd;
396d46373c1SJoseph Chen int i;
397d46373c1SJoseph Chen
398d46373c1SJoseph Chen fd = fopen(file, "wb");
399d46373c1SJoseph Chen if (!fd) {
400d46373c1SJoseph Chen fprintf(stderr, "Failed to create %s: %s\n",
401d46373c1SJoseph Chen file, strerror(errno));
402d46373c1SJoseph Chen return -ENOENT;
403d46373c1SJoseph Chen }
404d46373c1SJoseph Chen
405d46373c1SJoseph Chen for (i = 0; i < region_count; i++)
406d46373c1SJoseph Chen fwrite(region[i].data, region[i].size, 1, fd);
407d46373c1SJoseph Chen
408d46373c1SJoseph Chen fclose(fd);
409242e56faSJoseph Chen
410242e56faSJoseph Chen return 0;
411d46373c1SJoseph Chen }
412d46373c1SJoseph Chen
rsa_sign_with_key(RSA * rsa,struct padding_algo * padding_algo,struct checksum_algo * checksum_algo,const struct image_region region[],int region_count,uint8_t ** sigp,uint * sig_size)413219050bfSPhilippe Reynes static int rsa_sign_with_key(RSA *rsa, struct padding_algo *padding_algo,
414219050bfSPhilippe Reynes struct checksum_algo *checksum_algo,
415646257d1SHeiko Schocher const struct image_region region[], int region_count,
416646257d1SHeiko Schocher uint8_t **sigp, uint *sig_size)
41719c402afSSimon Glass {
41819c402afSSimon Glass EVP_PKEY *key;
419219050bfSPhilippe Reynes EVP_PKEY_CTX *ckey;
42019c402afSSimon Glass EVP_MD_CTX *context;
421624f7c07SPhilippe Reynes int ret = 0;
422624f7c07SPhilippe Reynes size_t size;
42319c402afSSimon Glass uint8_t *sig;
42419c402afSSimon Glass int i;
42519c402afSSimon Glass
42619c402afSSimon Glass key = EVP_PKEY_new();
42719c402afSSimon Glass if (!key)
42819c402afSSimon Glass return rsa_err("EVP_PKEY object creation failed");
42919c402afSSimon Glass
43019c402afSSimon Glass if (!EVP_PKEY_set1_RSA(key, rsa)) {
43119c402afSSimon Glass ret = rsa_err("EVP key setup failed");
43219c402afSSimon Glass goto err_set;
43319c402afSSimon Glass }
43419c402afSSimon Glass
43519c402afSSimon Glass size = EVP_PKEY_size(key);
43619c402afSSimon Glass sig = malloc(size);
43719c402afSSimon Glass if (!sig) {
438624f7c07SPhilippe Reynes fprintf(stderr, "Out of memory for signature (%zu bytes)\n",
43919c402afSSimon Glass size);
44019c402afSSimon Glass ret = -ENOMEM;
44119c402afSSimon Glass goto err_alloc;
44219c402afSSimon Glass }
44319c402afSSimon Glass
44419c402afSSimon Glass context = EVP_MD_CTX_create();
44519c402afSSimon Glass if (!context) {
44619c402afSSimon Glass ret = rsa_err("EVP context creation failed");
44719c402afSSimon Glass goto err_create;
44819c402afSSimon Glass }
44919c402afSSimon Glass EVP_MD_CTX_init(context);
450219050bfSPhilippe Reynes
451219050bfSPhilippe Reynes ckey = EVP_PKEY_CTX_new(key, NULL);
452219050bfSPhilippe Reynes if (!ckey) {
453219050bfSPhilippe Reynes ret = rsa_err("EVP key context creation failed");
454219050bfSPhilippe Reynes goto err_create;
455219050bfSPhilippe Reynes }
456219050bfSPhilippe Reynes
457219050bfSPhilippe Reynes if (EVP_DigestSignInit(context, &ckey,
458624f7c07SPhilippe Reynes checksum_algo->calculate_sign(),
459624f7c07SPhilippe Reynes NULL, key) <= 0) {
46019c402afSSimon Glass ret = rsa_err("Signer setup failed");
46119c402afSSimon Glass goto err_sign;
46219c402afSSimon Glass }
46319c402afSSimon Glass
46485289e9dSPhilippe Reynes #ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
46585289e9dSPhilippe Reynes if (padding_algo && !strcmp(padding_algo->name, "pss")) {
46685289e9dSPhilippe Reynes if (EVP_PKEY_CTX_set_rsa_padding(ckey,
46785289e9dSPhilippe Reynes RSA_PKCS1_PSS_PADDING) <= 0) {
46885289e9dSPhilippe Reynes ret = rsa_err("Signer padding setup failed");
46985289e9dSPhilippe Reynes goto err_sign;
47085289e9dSPhilippe Reynes }
47185289e9dSPhilippe Reynes }
47285289e9dSPhilippe Reynes #endif /* CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT */
47385289e9dSPhilippe Reynes
47419c402afSSimon Glass for (i = 0; i < region_count; i++) {
475624f7c07SPhilippe Reynes if (!EVP_DigestSignUpdate(context, region[i].data,
476624f7c07SPhilippe Reynes region[i].size)) {
47719c402afSSimon Glass ret = rsa_err("Signing data failed");
47819c402afSSimon Glass goto err_sign;
47919c402afSSimon Glass }
48019c402afSSimon Glass }
48119c402afSSimon Glass
482624f7c07SPhilippe Reynes if (!EVP_DigestSignFinal(context, sig, &size)) {
48319c402afSSimon Glass ret = rsa_err("Could not obtain signature");
48419c402afSSimon Glass goto err_sign;
48519c402afSSimon Glass }
486624f7c07SPhilippe Reynes
487624f7c07SPhilippe Reynes #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
488624f7c07SPhilippe Reynes (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
48919c402afSSimon Glass EVP_MD_CTX_cleanup(context);
490c3b43281SJelle van der Waa #else
491c3b43281SJelle van der Waa EVP_MD_CTX_reset(context);
492c3b43281SJelle van der Waa #endif
49319c402afSSimon Glass EVP_MD_CTX_destroy(context);
49419c402afSSimon Glass EVP_PKEY_free(key);
49519c402afSSimon Glass
496624f7c07SPhilippe Reynes debug("Got signature: %d bytes, expected %zu\n", *sig_size, size);
49719c402afSSimon Glass *sigp = sig;
49819c402afSSimon Glass *sig_size = size;
49919c402afSSimon Glass
500d46373c1SJoseph Chen gen_data2sign(region, region_count);
501d46373c1SJoseph Chen
50219c402afSSimon Glass return 0;
50319c402afSSimon Glass
50419c402afSSimon Glass err_sign:
50519c402afSSimon Glass EVP_MD_CTX_destroy(context);
50619c402afSSimon Glass err_create:
50719c402afSSimon Glass free(sig);
50819c402afSSimon Glass err_alloc:
50919c402afSSimon Glass err_set:
51019c402afSSimon Glass EVP_PKEY_free(key);
51119c402afSSimon Glass return ret;
51219c402afSSimon Glass }
51319c402afSSimon Glass
rsa_sign(struct image_sign_info * info,const struct image_region region[],int region_count,uint8_t ** sigp,uint * sig_len)51419c402afSSimon Glass int rsa_sign(struct image_sign_info *info,
51519c402afSSimon Glass const struct image_region region[], int region_count,
51619c402afSSimon Glass uint8_t **sigp, uint *sig_len)
51719c402afSSimon Glass {
51819c402afSSimon Glass RSA *rsa;
519f1ca1fdeSGeorge McCollister ENGINE *e = NULL;
52019c402afSSimon Glass int ret;
52119c402afSSimon Glass
52219c402afSSimon Glass ret = rsa_init();
52319c402afSSimon Glass if (ret)
52419c402afSSimon Glass return ret;
52519c402afSSimon Glass
526f1ca1fdeSGeorge McCollister if (info->engine_id) {
527f1ca1fdeSGeorge McCollister ret = rsa_engine_init(info->engine_id, &e);
528f1ca1fdeSGeorge McCollister if (ret)
529f1ca1fdeSGeorge McCollister goto err_engine;
530f1ca1fdeSGeorge McCollister }
531f1ca1fdeSGeorge McCollister
532f1ca1fdeSGeorge McCollister ret = rsa_get_priv_key(info->keydir, info->keyname, e, &rsa);
53319c402afSSimon Glass if (ret)
53419c402afSSimon Glass goto err_priv;
535219050bfSPhilippe Reynes ret = rsa_sign_with_key(rsa, info->padding, info->checksum, region,
536646257d1SHeiko Schocher region_count, sigp, sig_len);
53719c402afSSimon Glass if (ret)
53819c402afSSimon Glass goto err_sign;
53919c402afSSimon Glass
54019c402afSSimon Glass RSA_free(rsa);
541f1ca1fdeSGeorge McCollister if (info->engine_id)
542f1ca1fdeSGeorge McCollister rsa_engine_remove(e);
54319c402afSSimon Glass rsa_remove();
54419c402afSSimon Glass
54519c402afSSimon Glass return ret;
54619c402afSSimon Glass
54719c402afSSimon Glass err_sign:
54819c402afSSimon Glass RSA_free(rsa);
54919c402afSSimon Glass err_priv:
550f1ca1fdeSGeorge McCollister if (info->engine_id)
551f1ca1fdeSGeorge McCollister rsa_engine_remove(e);
552f1ca1fdeSGeorge McCollister err_engine:
55319c402afSSimon Glass rsa_remove();
55419c402afSSimon Glass return ret;
55519c402afSSimon Glass }
55619c402afSSimon Glass
55719c402afSSimon Glass /*
558e0f2f155SMichael van der Westhuizen * rsa_get_exponent(): - Get the public exponent from an RSA key
559e0f2f155SMichael van der Westhuizen */
rsa_get_exponent(RSA * key,uint64_t * e)560e0f2f155SMichael van der Westhuizen static int rsa_get_exponent(RSA *key, uint64_t *e)
561e0f2f155SMichael van der Westhuizen {
562e0f2f155SMichael van der Westhuizen int ret;
563e0f2f155SMichael van der Westhuizen BIGNUM *bn_te;
564c3b43281SJelle van der Waa const BIGNUM *key_e;
565e0f2f155SMichael van der Westhuizen uint64_t te;
566e0f2f155SMichael van der Westhuizen
567e0f2f155SMichael van der Westhuizen ret = -EINVAL;
568e0f2f155SMichael van der Westhuizen bn_te = NULL;
569e0f2f155SMichael van der Westhuizen
570e0f2f155SMichael van der Westhuizen if (!e)
571e0f2f155SMichael van der Westhuizen goto cleanup;
572e0f2f155SMichael van der Westhuizen
573c3b43281SJelle van der Waa RSA_get0_key(key, NULL, &key_e, NULL);
574c3b43281SJelle van der Waa if (BN_num_bits(key_e) > 64)
575e0f2f155SMichael van der Westhuizen goto cleanup;
576e0f2f155SMichael van der Westhuizen
577c3b43281SJelle van der Waa *e = BN_get_word(key_e);
578e0f2f155SMichael van der Westhuizen
579c3b43281SJelle van der Waa if (BN_num_bits(key_e) < 33) {
580e0f2f155SMichael van der Westhuizen ret = 0;
581e0f2f155SMichael van der Westhuizen goto cleanup;
582e0f2f155SMichael van der Westhuizen }
583e0f2f155SMichael van der Westhuizen
584c3b43281SJelle van der Waa bn_te = BN_dup(key_e);
585e0f2f155SMichael van der Westhuizen if (!bn_te)
586e0f2f155SMichael van der Westhuizen goto cleanup;
587e0f2f155SMichael van der Westhuizen
588e0f2f155SMichael van der Westhuizen if (!BN_rshift(bn_te, bn_te, 32))
589e0f2f155SMichael van der Westhuizen goto cleanup;
590e0f2f155SMichael van der Westhuizen
591e0f2f155SMichael van der Westhuizen if (!BN_mask_bits(bn_te, 32))
592e0f2f155SMichael van der Westhuizen goto cleanup;
593e0f2f155SMichael van der Westhuizen
594e0f2f155SMichael van der Westhuizen te = BN_get_word(bn_te);
595e0f2f155SMichael van der Westhuizen te <<= 32;
596e0f2f155SMichael van der Westhuizen *e |= te;
597e0f2f155SMichael van der Westhuizen ret = 0;
598e0f2f155SMichael van der Westhuizen
599e0f2f155SMichael van der Westhuizen cleanup:
600e0f2f155SMichael van der Westhuizen if (bn_te)
601e0f2f155SMichael van der Westhuizen BN_free(bn_te);
602e0f2f155SMichael van der Westhuizen
603e0f2f155SMichael van der Westhuizen return ret;
604e0f2f155SMichael van der Westhuizen }
605e0f2f155SMichael van der Westhuizen
606e0f2f155SMichael van der Westhuizen /*
60719c402afSSimon Glass * rsa_get_params(): - Get the important parameters of an RSA public key
60819c402afSSimon Glass */
rsa_get_params(RSA * key,uint64_t * exponent,uint32_t * n0_invp,BIGNUM ** modulusp,BIGNUM ** exponent_BN,BIGNUM ** r_squaredp,BIGNUM ** c_factorp,BIGNUM ** np_factorp)609e0f2f155SMichael van der Westhuizen int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
610008ec9b4SJoseph Chen BIGNUM **modulusp, BIGNUM **exponent_BN, BIGNUM **r_squaredp,
611008ec9b4SJoseph Chen BIGNUM **c_factorp, BIGNUM **np_factorp)
61219c402afSSimon Glass {
613*bc61c807SYi Liu BIGNUM *big1, *big2, *big32, *big2_32, *big4100, *big2180, *big4228;
614008ec9b4SJoseph Chen BIGNUM *n, *e, *r, *r_squared, *tmp, *c_factor, *np_factor;
615008ec9b4SJoseph Chen const BIGNUM *key_n, *key_e;
61619c402afSSimon Glass BN_CTX *bn_ctx = BN_CTX_new();
61719c402afSSimon Glass int ret = 0;
61819c402afSSimon Glass
61919c402afSSimon Glass /* Initialize BIGNUMs */
62019c402afSSimon Glass big1 = BN_new();
62119c402afSSimon Glass big2 = BN_new();
62219c402afSSimon Glass big32 = BN_new();
623008ec9b4SJoseph Chen big4100 = BN_new();
624008ec9b4SJoseph Chen big2180 = BN_new();
625*bc61c807SYi Liu big4228 = BN_new();
626008ec9b4SJoseph Chen
62719c402afSSimon Glass r = BN_new();
62819c402afSSimon Glass r_squared = BN_new();
629008ec9b4SJoseph Chen c_factor = BN_new();
630008ec9b4SJoseph Chen np_factor = BN_new();
63119c402afSSimon Glass tmp = BN_new();
63219c402afSSimon Glass big2_32 = BN_new();
63319c402afSSimon Glass n = BN_new();
634008ec9b4SJoseph Chen e = BN_new();
635*bc61c807SYi Liu if (!big1 || !big2 || !big32 || !big4100 || !big2180 || !big4228 || !r ||
636008ec9b4SJoseph Chen !r_squared || !tmp || !big2_32 || !n || !e ||
637008ec9b4SJoseph Chen !c_factor || !np_factor) {
63819c402afSSimon Glass fprintf(stderr, "Out of memory (bignum)\n");
63919c402afSSimon Glass return -ENOMEM;
64019c402afSSimon Glass }
64119c402afSSimon Glass
642e0f2f155SMichael van der Westhuizen if (0 != rsa_get_exponent(key, exponent))
643e0f2f155SMichael van der Westhuizen ret = -1;
644e0f2f155SMichael van der Westhuizen
645008ec9b4SJoseph Chen RSA_get0_key(key, &key_n, &key_e, NULL);
646008ec9b4SJoseph Chen if (!BN_copy(n, key_n) || !BN_copy(e, key_e) ||
647008ec9b4SJoseph Chen !BN_set_word(big1, 1L) ||
648008ec9b4SJoseph Chen !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L) ||
649*bc61c807SYi Liu !BN_set_word(big4100, 4100L) || !BN_set_word(big2180, 2180L) ||
650*bc61c807SYi Liu !BN_set_word(big4228, 4228L))
65119c402afSSimon Glass ret = -1;
65219c402afSSimon Glass
65319c402afSSimon Glass /* big2_32 = 2^32 */
65419c402afSSimon Glass if (!BN_exp(big2_32, big2, big32, bn_ctx))
65519c402afSSimon Glass ret = -1;
65619c402afSSimon Glass
65719c402afSSimon Glass /* Calculate n0_inv = -1 / n[0] mod 2^32 */
65819c402afSSimon Glass if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) ||
65919c402afSSimon Glass !BN_sub(tmp, big2_32, tmp))
66019c402afSSimon Glass ret = -1;
66119c402afSSimon Glass *n0_invp = BN_get_word(tmp);
66219c402afSSimon Glass
66319c402afSSimon Glass /* Calculate R = 2^(# of key bits) */
66419c402afSSimon Glass if (!BN_set_word(tmp, BN_num_bits(n)) ||
66519c402afSSimon Glass !BN_exp(r, big2, tmp, bn_ctx))
66619c402afSSimon Glass ret = -1;
66719c402afSSimon Glass
66819c402afSSimon Glass /* Calculate r_squared = R^2 mod n */
66919c402afSSimon Glass if (!BN_copy(r_squared, r) ||
67019c402afSSimon Glass !BN_mul(tmp, r_squared, r, bn_ctx) ||
67119c402afSSimon Glass !BN_mod(r_squared, tmp, n, bn_ctx))
67219c402afSSimon Glass ret = -1;
67319c402afSSimon Glass
674008ec9b4SJoseph Chen /* Calculate c_factor = 2^4100 mod n */
675008ec9b4SJoseph Chen if (!BN_exp(tmp, big2, big4100, bn_ctx) ||
676008ec9b4SJoseph Chen !BN_mod(c_factor, tmp, n, bn_ctx))
677008ec9b4SJoseph Chen ret = -1;
678008ec9b4SJoseph Chen
679008ec9b4SJoseph Chen /* Calculate np_factor = 2^2180 div n */
680*bc61c807SYi Liu if (BN_num_bits(n) == 2048) {
681008ec9b4SJoseph Chen if (!BN_exp(tmp, big2, big2180, bn_ctx) ||
682008ec9b4SJoseph Chen !BN_div(np_factor, NULL, tmp, n, bn_ctx))
683008ec9b4SJoseph Chen ret = -1;
684*bc61c807SYi Liu } else {/* Calculate 4096 np_factor = 2^4228 div n */
685*bc61c807SYi Liu if (!BN_exp(tmp, big2, big4228, bn_ctx) ||
686*bc61c807SYi Liu !BN_div(np_factor, NULL, tmp, n, bn_ctx))
687*bc61c807SYi Liu ret = -1;
688*bc61c807SYi Liu }
689008ec9b4SJoseph Chen
69019c402afSSimon Glass *modulusp = n;
691008ec9b4SJoseph Chen *exponent_BN = e;
69219c402afSSimon Glass *r_squaredp = r_squared;
693008ec9b4SJoseph Chen *c_factorp = c_factor;
694008ec9b4SJoseph Chen *np_factorp = np_factor;
69519c402afSSimon Glass
69619c402afSSimon Glass BN_free(big1);
69719c402afSSimon Glass BN_free(big2);
69819c402afSSimon Glass BN_free(big32);
699008ec9b4SJoseph Chen BN_free(big4100);
700008ec9b4SJoseph Chen BN_free(big2180);
701*bc61c807SYi Liu BN_free(big4228);
70219c402afSSimon Glass BN_free(r);
70319c402afSSimon Glass BN_free(tmp);
70419c402afSSimon Glass BN_free(big2_32);
70519c402afSSimon Glass if (ret) {
70619c402afSSimon Glass fprintf(stderr, "Bignum operations failed\n");
70719c402afSSimon Glass return -ENOMEM;
70819c402afSSimon Glass }
70919c402afSSimon Glass
71019c402afSSimon Glass return ret;
71119c402afSSimon Glass }
71219c402afSSimon Glass
rsa_convert_big_endian(uint32_t * dst,const uint32_t * src,int total_len,int convert_len)713781ee9b3SJason Zhu static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src,
714781ee9b3SJason Zhu int total_len, int convert_len)
715b6ea0cb4SJoseph Chen {
716781ee9b3SJason Zhu int total_wd, convert_wd, i;
717b6ea0cb4SJoseph Chen
718781ee9b3SJason Zhu if (total_len < convert_len)
719781ee9b3SJason Zhu convert_len = total_len;
720781ee9b3SJason Zhu
721781ee9b3SJason Zhu total_wd = total_len / sizeof(uint32_t);
722781ee9b3SJason Zhu convert_wd = convert_len / sizeof(uint32_t);
723781ee9b3SJason Zhu for (i = 0; i < convert_wd; i++)
724781ee9b3SJason Zhu dst[i] = fdt32_to_cpu(src[total_wd - 1 - i]);
725b6ea0cb4SJoseph Chen }
726b6ea0cb4SJoseph Chen
rsa_set_key_hash(void * keydest,int key_node,int key_len,const char * csum_algo)727b6ea0cb4SJoseph Chen static int rsa_set_key_hash(void *keydest, int key_node,
728b6ea0cb4SJoseph Chen int key_len, const char *csum_algo)
729b6ea0cb4SJoseph Chen {
730b6ea0cb4SJoseph Chen const void *rsa_n, *rsa_e, *rsa_c, *rsa_np;
731b6ea0cb4SJoseph Chen void *n, *e, *c, *np;
732b6ea0cb4SJoseph Chen uint8_t value[FIT_MAX_HASH_LEN];
733b6ea0cb4SJoseph Chen char hash_c[] = "hash@c";
734b6ea0cb4SJoseph Chen char hash_np[] = "hash@np";
735b6ea0cb4SJoseph Chen char *rsa_key;
736b6ea0cb4SJoseph Chen int hash_node;
737b6ea0cb4SJoseph Chen int value_len;
738b6ea0cb4SJoseph Chen int ret = -ENOSPC;
739b6ea0cb4SJoseph Chen
740781ee9b3SJason Zhu rsa_key = calloc(key_len * 3, sizeof(char));
741b6ea0cb4SJoseph Chen if (!rsa_key)
742b6ea0cb4SJoseph Chen return -ENOSPC;
743b6ea0cb4SJoseph Chen
744b6ea0cb4SJoseph Chen rsa_n = fdt_getprop(keydest, key_node, "rsa,modulus", NULL);
745b6ea0cb4SJoseph Chen rsa_e = fdt_getprop(keydest, key_node, "rsa,exponent-BN", NULL);
746b6ea0cb4SJoseph Chen rsa_c = fdt_getprop(keydest, key_node, "rsa,c", NULL);
747b6ea0cb4SJoseph Chen rsa_np = fdt_getprop(keydest, key_node, "rsa,np", NULL);
748b6ea0cb4SJoseph Chen if (!rsa_c || !rsa_np || !rsa_n || !rsa_e)
749b6ea0cb4SJoseph Chen goto err_nospc;
750b6ea0cb4SJoseph Chen
751b6ea0cb4SJoseph Chen n = rsa_key;
752781ee9b3SJason Zhu e = rsa_key + CONFIG_RSA_N_SIZE;
753781ee9b3SJason Zhu rsa_convert_big_endian(n, rsa_n, key_len, CONFIG_RSA_N_SIZE);
754781ee9b3SJason Zhu rsa_convert_big_endian(e, rsa_e, key_len, CONFIG_RSA_E_SIZE);
755b6ea0cb4SJoseph Chen
756b6ea0cb4SJoseph Chen /* hash@c node: n, e, c */
757781ee9b3SJason Zhu c = rsa_key + CONFIG_RSA_N_SIZE + CONFIG_RSA_E_SIZE;
758781ee9b3SJason Zhu rsa_convert_big_endian(c, rsa_c, key_len, CONFIG_RSA_C_SIZE);
759b6ea0cb4SJoseph Chen hash_node = fdt_add_subnode(keydest, key_node, hash_c);
760b6ea0cb4SJoseph Chen if (hash_node < 0)
761b6ea0cb4SJoseph Chen goto err_nospc;
762b6ea0cb4SJoseph Chen ret = calculate_hash(rsa_key, key_len * 3, csum_algo, value, &value_len);
763b6ea0cb4SJoseph Chen if (ret)
764b6ea0cb4SJoseph Chen goto err_nospc;
765b6ea0cb4SJoseph Chen ret = fdt_setprop(keydest, hash_node, FIT_VALUE_PROP, value, value_len);
766b6ea0cb4SJoseph Chen if (ret)
767b6ea0cb4SJoseph Chen goto err_nospc;
768b6ea0cb4SJoseph Chen ret = fdt_setprop_string(keydest, hash_node, FIT_ALGO_PROP, csum_algo);
769b6ea0cb4SJoseph Chen if (ret < 0)
770b6ea0cb4SJoseph Chen goto err_nospc;
771b6ea0cb4SJoseph Chen
772b6ea0cb4SJoseph Chen /* hash@np node: n, e, np */
773781ee9b3SJason Zhu np = rsa_key + CONFIG_RSA_N_SIZE + CONFIG_RSA_E_SIZE;
774781ee9b3SJason Zhu rsa_convert_big_endian(np, rsa_np, key_len, CONFIG_RSA_C_SIZE);
775b6ea0cb4SJoseph Chen hash_node = fdt_add_subnode(keydest, key_node, hash_np);
776b6ea0cb4SJoseph Chen if (hash_node < 0)
777b6ea0cb4SJoseph Chen goto err_nospc;
778b6ea0cb4SJoseph Chen
779781ee9b3SJason Zhu ret = calculate_hash(rsa_key, CONFIG_RSA_N_SIZE + CONFIG_RSA_E_SIZE + CONFIG_RSA_C_SIZE,
780781ee9b3SJason Zhu csum_algo, value, &value_len);
781b6ea0cb4SJoseph Chen if (ret)
782b6ea0cb4SJoseph Chen goto err_nospc;
783b6ea0cb4SJoseph Chen ret = fdt_setprop(keydest, hash_node, FIT_VALUE_PROP, value, value_len);
784b6ea0cb4SJoseph Chen if (ret < 0)
785b6ea0cb4SJoseph Chen goto err_nospc;
786b6ea0cb4SJoseph Chen ret = fdt_setprop_string(keydest, hash_node, FIT_ALGO_PROP, csum_algo);
787b6ea0cb4SJoseph Chen
788b6ea0cb4SJoseph Chen err_nospc:
789b6ea0cb4SJoseph Chen if (rsa_key)
790b6ea0cb4SJoseph Chen free(rsa_key);
791b6ea0cb4SJoseph Chen
792b6ea0cb4SJoseph Chen return ret ? -ENOSPC : 0;
793b6ea0cb4SJoseph Chen }
794b6ea0cb4SJoseph Chen
fdt_add_bignum(void * blob,int noffset,const char * prop_name,BIGNUM * num,int num_bits)79519c402afSSimon Glass static int fdt_add_bignum(void *blob, int noffset, const char *prop_name,
79619c402afSSimon Glass BIGNUM *num, int num_bits)
79719c402afSSimon Glass {
79819c402afSSimon Glass int nwords = num_bits / 32;
79919c402afSSimon Glass int size;
80019c402afSSimon Glass uint32_t *buf, *ptr;
80119c402afSSimon Glass BIGNUM *tmp, *big2, *big32, *big2_32;
80219c402afSSimon Glass BN_CTX *ctx;
80319c402afSSimon Glass int ret;
80419c402afSSimon Glass
80519c402afSSimon Glass tmp = BN_new();
80619c402afSSimon Glass big2 = BN_new();
80719c402afSSimon Glass big32 = BN_new();
80819c402afSSimon Glass big2_32 = BN_new();
80919c402afSSimon Glass if (!tmp || !big2 || !big32 || !big2_32) {
81019c402afSSimon Glass fprintf(stderr, "Out of memory (bignum)\n");
81119c402afSSimon Glass return -ENOMEM;
81219c402afSSimon Glass }
81319c402afSSimon Glass ctx = BN_CTX_new();
81419c402afSSimon Glass if (!tmp) {
81519c402afSSimon Glass fprintf(stderr, "Out of memory (bignum context)\n");
81619c402afSSimon Glass return -ENOMEM;
81719c402afSSimon Glass }
81819c402afSSimon Glass BN_set_word(big2, 2L);
81919c402afSSimon Glass BN_set_word(big32, 32L);
82019c402afSSimon Glass BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */
82119c402afSSimon Glass
82219c402afSSimon Glass size = nwords * sizeof(uint32_t);
82319c402afSSimon Glass buf = malloc(size);
82419c402afSSimon Glass if (!buf) {
82519c402afSSimon Glass fprintf(stderr, "Out of memory (%d bytes)\n", size);
82619c402afSSimon Glass return -ENOMEM;
82719c402afSSimon Glass }
82819c402afSSimon Glass
82919c402afSSimon Glass /* Write out modulus as big endian array of integers */
83019c402afSSimon Glass for (ptr = buf + nwords - 1; ptr >= buf; ptr--) {
83119c402afSSimon Glass BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */
83219c402afSSimon Glass *ptr = cpu_to_fdt32(BN_get_word(tmp));
83319c402afSSimon Glass BN_rshift(num, num, 32); /* N = N/B */
83419c402afSSimon Glass }
83519c402afSSimon Glass
836713fb2dcSmario.six@gdsys.cc /*
837713fb2dcSmario.six@gdsys.cc * We try signing with successively increasing size values, so this
838713fb2dcSmario.six@gdsys.cc * might fail several times
839713fb2dcSmario.six@gdsys.cc */
84019c402afSSimon Glass ret = fdt_setprop(blob, noffset, prop_name, buf, size);
8412b9ec762Smario.six@gdsys.cc if (ret)
8422b9ec762Smario.six@gdsys.cc return -FDT_ERR_NOSPACE;
84319c402afSSimon Glass free(buf);
84419c402afSSimon Glass BN_free(tmp);
84519c402afSSimon Glass BN_free(big2);
84619c402afSSimon Glass BN_free(big32);
84719c402afSSimon Glass BN_free(big2_32);
84819c402afSSimon Glass
84919c402afSSimon Glass return ret;
85019c402afSSimon Glass }
85119c402afSSimon Glass
rsa_add_verify_data(struct image_sign_info * info,void * keydest)85219c402afSSimon Glass int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
85319c402afSSimon Glass {
854008ec9b4SJoseph Chen BIGNUM *modulus, *exponent_BN, *r_squared, *c_factor, *np_factor;
855e0f2f155SMichael van der Westhuizen uint64_t exponent;
85619c402afSSimon Glass uint32_t n0_inv;
85719c402afSSimon Glass int parent, node;
85819c402afSSimon Glass char name[100];
85919c402afSSimon Glass int ret;
86019c402afSSimon Glass int bits;
86119c402afSSimon Glass RSA *rsa;
862f1ca1fdeSGeorge McCollister ENGINE *e = NULL;
86319c402afSSimon Glass
86419c402afSSimon Glass debug("%s: Getting verification data\n", __func__);
865f1ca1fdeSGeorge McCollister if (info->engine_id) {
866f1ca1fdeSGeorge McCollister ret = rsa_engine_init(info->engine_id, &e);
86719c402afSSimon Glass if (ret)
86819c402afSSimon Glass return ret;
869f1ca1fdeSGeorge McCollister }
870f1ca1fdeSGeorge McCollister ret = rsa_get_pub_key(info->keydir, info->keyname, e, &rsa);
871f1ca1fdeSGeorge McCollister if (ret)
872f1ca1fdeSGeorge McCollister goto err_get_pub_key;
873008ec9b4SJoseph Chen ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus,
874008ec9b4SJoseph Chen &exponent_BN, &r_squared, &c_factor, &np_factor);
87519c402afSSimon Glass if (ret)
876f1ca1fdeSGeorge McCollister goto err_get_params;
87719c402afSSimon Glass bits = BN_num_bits(modulus);
87819c402afSSimon Glass parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
87919c402afSSimon Glass if (parent == -FDT_ERR_NOTFOUND) {
88019c402afSSimon Glass parent = fdt_add_subnode(keydest, 0, FIT_SIG_NODENAME);
88119c402afSSimon Glass if (parent < 0) {
882597a8b2cSSimon Glass ret = parent;
883597a8b2cSSimon Glass if (ret != -FDT_ERR_NOSPACE) {
88419c402afSSimon Glass fprintf(stderr, "Couldn't create signature node: %s\n",
88519c402afSSimon Glass fdt_strerror(parent));
88619c402afSSimon Glass }
88719c402afSSimon Glass }
888597a8b2cSSimon Glass }
889597a8b2cSSimon Glass if (ret)
890597a8b2cSSimon Glass goto done;
89119c402afSSimon Glass
89219c402afSSimon Glass /* Either create or overwrite the named key node */
89319c402afSSimon Glass snprintf(name, sizeof(name), "key-%s", info->keyname);
89419c402afSSimon Glass node = fdt_subnode_offset(keydest, parent, name);
89519c402afSSimon Glass if (node == -FDT_ERR_NOTFOUND) {
89619c402afSSimon Glass node = fdt_add_subnode(keydest, parent, name);
89719c402afSSimon Glass if (node < 0) {
898597a8b2cSSimon Glass ret = node;
899597a8b2cSSimon Glass if (ret != -FDT_ERR_NOSPACE) {
90019c402afSSimon Glass fprintf(stderr, "Could not create key subnode: %s\n",
90119c402afSSimon Glass fdt_strerror(node));
902597a8b2cSSimon Glass }
90319c402afSSimon Glass }
90419c402afSSimon Glass } else if (node < 0) {
90519c402afSSimon Glass fprintf(stderr, "Cannot select keys parent: %s\n",
90619c402afSSimon Glass fdt_strerror(node));
907597a8b2cSSimon Glass ret = node;
90819c402afSSimon Glass }
90919c402afSSimon Glass
910597a8b2cSSimon Glass if (!ret) {
91119c402afSSimon Glass ret = fdt_setprop_string(keydest, node, "key-name-hint",
91219c402afSSimon Glass info->keyname);
913597a8b2cSSimon Glass }
9144f427a42SSimon Glass if (!ret)
9154f427a42SSimon Glass ret = fdt_setprop_u32(keydest, node, "rsa,num-bits", bits);
9164f427a42SSimon Glass if (!ret)
9174f427a42SSimon Glass ret = fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
9184f427a42SSimon Glass if (!ret) {
919e0f2f155SMichael van der Westhuizen ret = fdt_setprop_u64(keydest, node, "rsa,exponent", exponent);
920e0f2f155SMichael van der Westhuizen }
921e0f2f155SMichael van der Westhuizen if (!ret) {
922008ec9b4SJoseph Chen ret = fdt_add_bignum(keydest, node, "rsa,exponent-BN",
923008ec9b4SJoseph Chen exponent_BN, bits);
924008ec9b4SJoseph Chen }
925008ec9b4SJoseph Chen if (!ret) {
9264f427a42SSimon Glass ret = fdt_add_bignum(keydest, node, "rsa,modulus", modulus,
9274f427a42SSimon Glass bits);
9284f427a42SSimon Glass }
9294f427a42SSimon Glass if (!ret) {
9304f427a42SSimon Glass ret = fdt_add_bignum(keydest, node, "rsa,r-squared", r_squared,
9314f427a42SSimon Glass bits);
9324f427a42SSimon Glass }
9334f427a42SSimon Glass if (!ret) {
934008ec9b4SJoseph Chen ret = fdt_add_bignum(keydest, node, "rsa,c", c_factor,
935008ec9b4SJoseph Chen bits);
936008ec9b4SJoseph Chen }
937008ec9b4SJoseph Chen if (!ret) {
938008ec9b4SJoseph Chen ret = fdt_add_bignum(keydest, node, "rsa,np", np_factor,
939008ec9b4SJoseph Chen bits);
940008ec9b4SJoseph Chen }
941008ec9b4SJoseph Chen if (!ret) {
9424f427a42SSimon Glass ret = fdt_setprop_string(keydest, node, FIT_ALGO_PROP,
94383dd98e0SAndrew Duda info->name);
9444f427a42SSimon Glass }
9452b9ec762Smario.six@gdsys.cc if (!ret && info->require_keys) {
9464f427a42SSimon Glass ret = fdt_setprop_string(keydest, node, "required",
94719c402afSSimon Glass info->require_keys);
94819c402afSSimon Glass }
949b6ea0cb4SJoseph Chen if (!ret) {
950b6ea0cb4SJoseph Chen ret = rsa_set_key_hash(keydest, node, info->crypto->key_len,
951b6ea0cb4SJoseph Chen info->checksum->name);
952b6ea0cb4SJoseph Chen }
953597a8b2cSSimon Glass done:
95419c402afSSimon Glass BN_free(modulus);
95519c402afSSimon Glass BN_free(r_squared);
95619c402afSSimon Glass if (ret)
957f1ca1fdeSGeorge McCollister ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
958f1ca1fdeSGeorge McCollister err_get_params:
959f1ca1fdeSGeorge McCollister RSA_free(rsa);
960f1ca1fdeSGeorge McCollister err_get_pub_key:
961f1ca1fdeSGeorge McCollister if (info->engine_id)
962f1ca1fdeSGeorge McCollister rsa_engine_remove(e);
96319c402afSSimon Glass
964f1ca1fdeSGeorge McCollister return ret;
96519c402afSSimon Glass }
966