]>
Commit | Line | Data |
---|---|---|
4c17e5f6 AG |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright (c) 2020, Alexandru Gagniuc <[email protected]> | |
4 | * Copyright (c) 2013, Google Inc. | |
5 | */ | |
6 | ||
7 | #include <libfdt.h> | |
8 | #include <u-boot/fdt-libcrypto.h> | |
9 | ||
10 | int fdt_add_bignum(void *blob, int noffset, const char *prop_name, | |
11 | BIGNUM *num, int num_bits) | |
12 | { | |
13 | int nwords = num_bits / 32; | |
14 | int size; | |
15 | uint32_t *buf, *ptr; | |
16 | BIGNUM *tmp, *big2, *big32, *big2_32; | |
17 | BN_CTX *ctx; | |
18 | int ret; | |
19 | ||
20 | tmp = BN_new(); | |
21 | big2 = BN_new(); | |
22 | big32 = BN_new(); | |
23 | big2_32 = BN_new(); | |
24 | ||
25 | /* | |
26 | * Note: This code assumes that all of the above succeed, or all fail. | |
27 | * In practice memory allocations generally do not fail (unless the | |
28 | * process is killed), so it does not seem worth handling each of these | |
29 | * as a separate case. Technicaly this could leak memory on failure, | |
30 | * but a) it won't happen in practice, and b) it doesn't matter as we | |
31 | * will immediately exit with a failure code. | |
32 | */ | |
33 | if (!tmp || !big2 || !big32 || !big2_32) { | |
34 | fprintf(stderr, "Out of memory (bignum)\n"); | |
35 | return -ENOMEM; | |
36 | } | |
37 | ctx = BN_CTX_new(); | |
38 | if (!ctx) { | |
39 | fprintf(stderr, "Out of memory (bignum context)\n"); | |
40 | return -ENOMEM; | |
41 | } | |
42 | BN_set_word(big2, 2L); | |
43 | BN_set_word(big32, 32L); | |
44 | BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */ | |
45 | ||
46 | size = nwords * sizeof(uint32_t); | |
47 | buf = malloc(size); | |
48 | if (!buf) { | |
49 | fprintf(stderr, "Out of memory (%d bytes)\n", size); | |
50 | return -ENOMEM; | |
51 | } | |
52 | ||
53 | /* Write out modulus as big endian array of integers */ | |
54 | for (ptr = buf + nwords - 1; ptr >= buf; ptr--) { | |
55 | BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */ | |
56 | *ptr = cpu_to_fdt32(BN_get_word(tmp)); | |
57 | BN_rshift(num, num, 32); /* N = N/B */ | |
58 | } | |
59 | ||
60 | /* | |
61 | * We try signing with successively increasing size values, so this | |
62 | * might fail several times | |
63 | */ | |
64 | ret = fdt_setprop(blob, noffset, prop_name, buf, size); | |
65 | free(buf); | |
66 | BN_free(tmp); | |
67 | BN_free(big2); | |
68 | BN_free(big32); | |
69 | BN_free(big2_32); | |
70 | ||
71 | return ret ? -FDT_ERR_NOSPACE : 0; | |
72 | } |