]>
Commit | Line | Data |
---|---|---|
f3090fc7 | 1 | /* |
da1c088f | 2 | * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. |
f3090fc7 | 3 | * |
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use | |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
10 | #include <openssl/bn.h> | |
11 | #include <openssl/evp.h> | |
12 | #include <openssl/core_names.h> | |
13 | #include <openssl/kdf.h> | |
14 | #include "internal/deterministic_nonce.h" | |
15 | ||
16 | /* | |
17 | * Convert a Bit String to an Integer (See RFC 6979 Section 2.3.2) | |
18 | * | |
19 | * Params: | |
20 | * out The returned Integer as a BIGNUM | |
21 | * qlen_bits The maximum size of the returned integer in bits. The returned | |
22 | * Integer is shifted right if inlen is larger than qlen_bits.. | |
23 | * in, inlen The input Bit String (in bytes). | |
24 | * Returns: 1 if successful, or 0 otherwise. | |
25 | */ | |
26 | static int bits2int(BIGNUM *out, int qlen_bits, | |
27 | const unsigned char *in, size_t inlen) | |
28 | { | |
29 | int blen_bits = inlen * 8; | |
30 | int shift; | |
31 | ||
32 | if (BN_bin2bn(in, (int)inlen, out) == NULL) | |
33 | return 0; | |
34 | ||
35 | shift = blen_bits - qlen_bits; | |
36 | if (shift > 0) | |
37 | return BN_rshift(out, out, shift); | |
38 | return 1; | |
39 | } | |
40 | ||
41 | /* | |
42 | * Convert an Integer to an Octet String (See RFC 6979 2.3.3). | |
43 | * The value is zero padded if required. | |
44 | * | |
45 | * Params: | |
46 | * out The returned Octet String | |
47 | * num The input Integer | |
48 | * rlen The required size of the returned Octet String in bytes | |
eb4129e1 | 49 | * Returns: 1 if successful, or 0 otherwise. |
f3090fc7 | 50 | */ |
51 | static int int2octets(unsigned char *out, const BIGNUM *num, int rlen) | |
52 | { | |
53 | return BN_bn2binpad(num, out, rlen) >= 0; | |
54 | } | |
55 | ||
56 | /* | |
57 | * Convert a Bit String to an Octet String (See RFC 6979 Section 2.3.4) | |
58 | * | |
59 | * Params: | |
60 | * out The returned octet string. | |
61 | * q The modulus | |
62 | * qlen_bits The length of q in bits | |
63 | * rlen The value of qlen_bits rounded up to the nearest 8 bits. | |
64 | * in, inlen The input bit string (in bytes) | |
65 | * Returns: 1 if successful, or 0 otherwise. | |
66 | */ | |
67 | static int bits2octets(unsigned char *out, const BIGNUM *q, int qlen_bits, | |
68 | int rlen, const unsigned char *in, size_t inlen) | |
69 | { | |
70 | int ret = 0; | |
71 | BIGNUM *z = BN_new(); | |
72 | ||
73 | if (z == NULL | |
74 | || !bits2int(z, qlen_bits, in, inlen)) | |
75 | goto err; | |
76 | ||
77 | /* z2 = z1 mod q (Do a simple subtract, since z1 < 2^qlen_bits) */ | |
78 | if (BN_cmp(z, q) >= 0 | |
79 | && !BN_usub(z, z, q)) | |
80 | goto err; | |
81 | ||
82 | ret = int2octets(out, z, rlen); | |
83 | err: | |
84 | BN_free(z); | |
85 | return ret; | |
86 | } | |
87 | ||
88 | /* | |
89 | * Setup a KDF HMAC_DRBG object using fixed entropy and nonce data. | |
90 | * | |
91 | * Params: | |
92 | * digestname The digest name for the HMAC | |
93 | * entropy, entropylen A fixed input entropy buffer | |
94 | * nonce, noncelen A fixed input nonce buffer | |
95 | * libctx, propq Are used for fetching algorithms | |
96 | * | |
97 | * Returns: The created KDF HMAC_DRBG object if successful, or NULL otherwise. | |
98 | */ | |
99 | static EVP_KDF_CTX *kdf_setup(const char *digestname, | |
100 | const unsigned char *entropy, size_t entropylen, | |
101 | const unsigned char *nonce, size_t noncelen, | |
102 | OSSL_LIB_CTX *libctx, const char *propq) | |
103 | { | |
104 | EVP_KDF_CTX *ctx = NULL; | |
105 | EVP_KDF *kdf = NULL; | |
106 | OSSL_PARAM params[5], *p; | |
107 | ||
108 | kdf = EVP_KDF_fetch(libctx, "HMAC-DRBG-KDF", propq); | |
109 | ctx = EVP_KDF_CTX_new(kdf); | |
110 | EVP_KDF_free(kdf); | |
111 | if (ctx == NULL) | |
112 | goto err; | |
113 | ||
114 | p = params; | |
115 | *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, | |
116 | (char *)digestname, 0); | |
117 | if (propq != NULL) | |
118 | *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_PROPERTIES, | |
119 | (char *)propq, 0); | |
120 | *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_HMACDRBG_ENTROPY, | |
121 | (void *)entropy, entropylen); | |
122 | *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_HMACDRBG_NONCE, | |
123 | (void *)nonce, noncelen); | |
124 | *p = OSSL_PARAM_construct_end(); | |
125 | ||
126 | if (EVP_KDF_CTX_set_params(ctx, params) <= 0) | |
127 | goto err; | |
128 | ||
129 | return ctx; | |
130 | err: | |
131 | EVP_KDF_CTX_free(ctx); | |
132 | return NULL; | |
133 | } | |
134 | ||
135 | /* | |
136 | * Generate a Deterministic nonce 'k' for DSA/ECDSA as defined in | |
137 | * RFC 6979 Section 3.3. "Alternate Description of the Generation of k" | |
138 | * | |
139 | * Params: | |
140 | * out Returns the generated deterministic nonce 'k' | |
141 | * q A large prime number used for modulus operations for DSA and ECDSA. | |
142 | * priv The private key in the range [1, q-1] | |
143 | * hm, hmlen The digested message buffer in bytes | |
144 | * digestname The digest name used for signing. It is used as the HMAC digest. | |
145 | * libctx, propq Used for fetching algorithms | |
146 | * | |
147 | * Returns: 1 if successful, or 0 otherwise. | |
148 | */ | |
149 | int ossl_gen_deterministic_nonce_rfc6979(BIGNUM *out, const BIGNUM *q, | |
150 | const BIGNUM *priv, | |
151 | const unsigned char *hm, size_t hmlen, | |
152 | const char *digestname, | |
153 | OSSL_LIB_CTX *libctx, | |
154 | const char *propq) | |
155 | { | |
156 | EVP_KDF_CTX *kdfctx = NULL; | |
157 | int ret = 0, rlen = 0, qlen_bits = 0; | |
158 | unsigned char *entropyx = NULL, *nonceh = NULL, *T = NULL; | |
159 | size_t allocsz = 0; | |
160 | ||
5e42118d | 161 | if (out == NULL) |
162 | return 0; | |
163 | ||
f3090fc7 | 164 | qlen_bits = BN_num_bits(q); |
165 | if (qlen_bits == 0) | |
5e42118d | 166 | return 0; |
f3090fc7 | 167 | |
168 | /* Note rlen used here is in bytes since the input values are byte arrays */ | |
169 | rlen = (qlen_bits + 7) / 8; | |
170 | allocsz = 3 * rlen; | |
171 | ||
172 | /* Use a single alloc for the buffers T, nonceh and entropyx */ | |
173 | T = (unsigned char *)OPENSSL_zalloc(allocsz); | |
174 | if (T == NULL) | |
5e42118d | 175 | return 0; |
f3090fc7 | 176 | nonceh = T + rlen; |
177 | entropyx = nonceh + rlen; | |
178 | ||
179 | if (!int2octets(entropyx, priv, rlen) | |
180 | || !bits2octets(nonceh, q, qlen_bits, rlen, hm, hmlen)) | |
181 | goto end; | |
182 | ||
183 | kdfctx = kdf_setup(digestname, entropyx, rlen, nonceh, rlen, libctx, propq); | |
184 | if (kdfctx == NULL) | |
185 | goto end; | |
186 | ||
187 | do { | |
188 | if (!EVP_KDF_derive(kdfctx, T, rlen, NULL) | |
189 | || !bits2int(out, qlen_bits, T, rlen)) | |
190 | goto end; | |
191 | } while (BN_is_zero(out) || BN_is_one(out) || BN_cmp(out, q) >= 0); | |
192 | ret = 1; | |
193 | ||
194 | end: | |
195 | EVP_KDF_CTX_free(kdfctx); | |
196 | OPENSSL_clear_free(T, allocsz); | |
197 | return ret; | |
198 | } |