Line | Count | Source |
1 | | /* |
2 | | * Dropbear - a SSH2 server |
3 | | * |
4 | | * Copyright (c) 2002,2003 Matt Johnston |
5 | | * All rights reserved. |
6 | | * |
7 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
8 | | * of this software and associated documentation files (the "Software"), to deal |
9 | | * in the Software without restriction, including without limitation the rights |
10 | | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
11 | | * copies of the Software, and to permit persons to whom the Software is |
12 | | * furnished to do so, subject to the following conditions: |
13 | | * |
14 | | * The above copyright notice and this permission notice shall be included in |
15 | | * all copies or substantial portions of the Software. |
16 | | * |
17 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
18 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
19 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
20 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
21 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
22 | | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
23 | | * SOFTWARE. */ |
24 | | |
25 | | /* Perform RSA operations on data, including reading keys, signing and |
26 | | * verification. |
27 | | * |
28 | | * The format is specified in rfc2437, Applied Cryptography or The Handbook of |
29 | | * Applied Cryptography detail the general algorithm. */ |
30 | | |
31 | | #include "includes.h" |
32 | | #include "dbutil.h" |
33 | | #include "bignum.h" |
34 | | #include "rsa.h" |
35 | | #include "buffer.h" |
36 | | #include "ssh.h" |
37 | | #include "dbrandom.h" |
38 | | #include "signkey.h" |
39 | | |
40 | | #if DROPBEAR_RSA |
41 | | |
42 | | #if !(DROPBEAR_RSA_SHA1 || DROPBEAR_RSA_SHA256) |
43 | | #error Somehow RSA was enabled with neither DROPBEAR_RSA_SHA1 nor DROPBEAR_RSA_SHA256 |
44 | | #endif |
45 | | |
46 | | static void rsa_pad_em(const dropbear_rsa_key * key, |
47 | | const buffer *data_buf, mp_int * rsa_em, enum signature_type sigtype); |
48 | | |
49 | | /* Load a public rsa key from a buffer, initialising the values. |
50 | | * The key will have the same format as buf_put_rsa_key. |
51 | | * These should be freed with rsa_key_free. |
52 | | * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ |
53 | 0 | int buf_get_rsa_pub_key(buffer* buf, dropbear_rsa_key *key) { |
54 | |
|
55 | 0 | int ret = DROPBEAR_FAILURE; |
56 | 0 | TRACE(("enter buf_get_rsa_pub_key")) |
57 | 0 | dropbear_assert(key != NULL); |
58 | 0 | m_mp_alloc_init_multi(&key->e, &key->n, NULL); |
59 | 0 | key->d = NULL; |
60 | 0 | key->p = NULL; |
61 | 0 | key->q = NULL; |
62 | |
|
63 | 0 | buf_incrpos(buf, 4+SSH_SIGNKEY_RSA_LEN); /* int + "ssh-rsa" */ |
64 | |
|
65 | 0 | if (buf_getmpint(buf, key->e) == DROPBEAR_FAILURE |
66 | 0 | || buf_getmpint(buf, key->n) == DROPBEAR_FAILURE) { |
67 | 0 | TRACE(("leave buf_get_rsa_pub_key: failure")) |
68 | 0 | goto out; |
69 | 0 | } |
70 | | |
71 | 0 | if (mp_count_bits(key->n) < MIN_RSA_KEYLEN) { |
72 | 0 | dropbear_log(LOG_WARNING, "RSA key too short"); |
73 | 0 | goto out; |
74 | 0 | } |
75 | | |
76 | | /* 64 bit is limit used by openssl, so we won't block any keys in the wild */ |
77 | 0 | if (mp_count_bits(key->e) > 64) { |
78 | 0 | dropbear_log(LOG_WARNING, "RSA key bad e"); |
79 | 0 | goto out; |
80 | 0 | } |
81 | | |
82 | 0 | TRACE(("leave buf_get_rsa_pub_key: success")) |
83 | 0 | ret = DROPBEAR_SUCCESS; |
84 | 0 | out: |
85 | 0 | if (ret == DROPBEAR_FAILURE) { |
86 | 0 | m_mp_free_multi(&key->e, &key->n, NULL); |
87 | 0 | } |
88 | 0 | return ret; |
89 | 0 | } |
90 | | |
91 | | /* Same as buf_get_rsa_pub_key, but reads private bits at the end. |
92 | | * Loads a private rsa key from a buffer |
93 | | * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ |
94 | 0 | int buf_get_rsa_priv_key(buffer* buf, dropbear_rsa_key *key) { |
95 | 0 | int ret = DROPBEAR_FAILURE; |
96 | |
|
97 | 0 | TRACE(("enter buf_get_rsa_priv_key")) |
98 | 0 | dropbear_assert(key != NULL); |
99 | | |
100 | 0 | if (buf_get_rsa_pub_key(buf, key) == DROPBEAR_FAILURE) { |
101 | 0 | TRACE(("leave buf_get_rsa_priv_key: pub: ret == DROPBEAR_FAILURE")) |
102 | 0 | return DROPBEAR_FAILURE; |
103 | 0 | } |
104 | | |
105 | 0 | key->d = NULL; |
106 | 0 | key->p = NULL; |
107 | 0 | key->q = NULL; |
108 | |
|
109 | 0 | m_mp_alloc_init_multi(&key->d, NULL); |
110 | 0 | if (buf_getmpint(buf, key->d) == DROPBEAR_FAILURE) { |
111 | 0 | TRACE(("leave buf_get_rsa_priv_key: d: ret == DROPBEAR_FAILURE")) |
112 | 0 | goto out; |
113 | 0 | } |
114 | | |
115 | 0 | if (buf->pos == buf->len) { |
116 | | /* Keys without p or q are prior to Dropbear 0.33 from 2003. */ |
117 | 0 | dropbear_exit("RSA key format is ancient"); |
118 | 0 | } else { |
119 | 0 | m_mp_alloc_init_multi(&key->p, &key->q, NULL); |
120 | |
|
121 | 0 | if (buf_getmpint(buf, key->p) == DROPBEAR_FAILURE) { |
122 | 0 | TRACE(("leave buf_get_rsa_priv_key: p: ret == DROPBEAR_FAILURE")) |
123 | 0 | goto out; |
124 | 0 | } |
125 | | |
126 | 0 | if (buf_getmpint(buf, key->q) == DROPBEAR_FAILURE) { |
127 | 0 | TRACE(("leave buf_get_rsa_priv_key: q: ret == DROPBEAR_FAILURE")) |
128 | 0 | goto out; |
129 | 0 | } |
130 | 0 | } |
131 | | |
132 | 0 | ret = DROPBEAR_SUCCESS; |
133 | 0 | out: |
134 | 0 | if (ret == DROPBEAR_FAILURE) { |
135 | 0 | m_mp_free_multi(&key->d, &key->p, &key->q, NULL); |
136 | 0 | } |
137 | 0 | TRACE(("leave buf_get_rsa_priv_key")) |
138 | 0 | return ret; |
139 | 0 | } |
140 | | |
141 | | |
142 | | /* Clear and free the memory used by a public or private key */ |
143 | 2 | void rsa_key_free(dropbear_rsa_key *key) { |
144 | | |
145 | 2 | TRACE2(("enter rsa_key_free")) |
146 | | |
147 | 2 | if (key == NULL) { |
148 | 2 | TRACE2(("leave rsa_key_free: key == NULL")) |
149 | 2 | return; |
150 | 2 | } |
151 | 0 | m_mp_free_multi(&key->d, &key->e, &key->p, &key->q, &key->n, NULL); |
152 | 0 | m_free(key); |
153 | 0 | TRACE2(("leave rsa_key_free")) |
154 | 0 | } |
155 | | |
156 | | /* Put the public rsa key into the buffer in the required format: |
157 | | * |
158 | | * string "ssh-rsa" |
159 | | * mp_int e |
160 | | * mp_int n |
161 | | */ |
162 | 5 | void buf_put_rsa_pub_key(buffer* buf, const dropbear_rsa_key *key) { |
163 | | |
164 | 5 | TRACE(("enter buf_put_rsa_pub_key")) |
165 | 5 | dropbear_assert(key != NULL); |
166 | | |
167 | 0 | buf_putstring(buf, SSH_SIGNKEY_RSA, SSH_SIGNKEY_RSA_LEN); |
168 | 0 | buf_putmpint(buf, key->e); |
169 | 0 | buf_putmpint(buf, key->n); |
170 | |
|
171 | 0 | TRACE(("leave buf_put_rsa_pub_key")) |
172 | |
|
173 | 0 | } |
174 | | |
175 | | /* Same as buf_put_rsa_pub_key, but with the private "x" key appended */ |
176 | 0 | void buf_put_rsa_priv_key(buffer* buf, const dropbear_rsa_key *key) { |
177 | |
|
178 | 0 | TRACE(("enter buf_put_rsa_priv_key")) |
179 | |
|
180 | 0 | dropbear_assert(key != NULL); |
181 | 0 | buf_put_rsa_pub_key(buf, key); |
182 | 0 | buf_putmpint(buf, key->d); |
183 | | |
184 | | /* new versions have p and q, old versions don't */ |
185 | 0 | if (key->p) { |
186 | 0 | buf_putmpint(buf, key->p); |
187 | 0 | } |
188 | 0 | if (key->q) { |
189 | 0 | buf_putmpint(buf, key->q); |
190 | 0 | } |
191 | | |
192 | |
|
193 | 0 | TRACE(("leave buf_put_rsa_priv_key")) |
194 | |
|
195 | 0 | } |
196 | | |
197 | | #if DROPBEAR_SIGNKEY_VERIFY |
198 | | /* Verify a signature in buf, made on data by the key given. |
199 | | * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ |
200 | | int buf_rsa_verify(buffer * buf, const dropbear_rsa_key *key, |
201 | 0 | enum signature_type sigtype, const buffer *data_buf) { |
202 | 0 | unsigned int slen; |
203 | 0 | DEF_MP_INT(rsa_s); |
204 | 0 | DEF_MP_INT(rsa_mdash); |
205 | 0 | DEF_MP_INT(rsa_em); |
206 | 0 | int ret = DROPBEAR_FAILURE; |
207 | |
|
208 | 0 | TRACE(("enter buf_rsa_verify")) |
209 | |
|
210 | 0 | dropbear_assert(key != NULL); |
211 | | |
212 | 0 | m_mp_init_multi(&rsa_mdash, &rsa_s, &rsa_em, NULL); |
213 | |
|
214 | 0 | slen = buf_getint(buf); |
215 | 0 | if (slen != (unsigned int)mp_ubin_size(key->n)) { |
216 | 0 | TRACE(("bad size")) |
217 | 0 | goto out; |
218 | 0 | } |
219 | | |
220 | 0 | if (mp_from_ubin(&rsa_s, buf_getptr(buf, buf->len - buf->pos), |
221 | 0 | buf->len - buf->pos) != MP_OKAY) { |
222 | 0 | TRACE(("failed reading rsa_s")) |
223 | 0 | goto out; |
224 | 0 | } |
225 | | |
226 | | /* check that s <= n-1 */ |
227 | 0 | if (mp_cmp(&rsa_s, key->n) != MP_LT) { |
228 | 0 | TRACE(("s > n-1")) |
229 | 0 | goto out; |
230 | 0 | } |
231 | | |
232 | | /* create the magic PKCS padded value */ |
233 | 0 | rsa_pad_em(key, data_buf, &rsa_em, sigtype); |
234 | |
|
235 | 0 | if (mp_exptmod(&rsa_s, key->e, key->n, &rsa_mdash) != MP_OKAY) { |
236 | 0 | TRACE(("failed exptmod rsa_s")) |
237 | 0 | goto out; |
238 | 0 | } |
239 | | |
240 | 0 | if (mp_cmp(&rsa_em, &rsa_mdash) == MP_EQ) { |
241 | | /* signature is valid */ |
242 | 0 | TRACE(("success!")) |
243 | 0 | ret = DROPBEAR_SUCCESS; |
244 | 0 | } |
245 | |
|
246 | 0 | out: |
247 | 0 | mp_clear_multi(&rsa_mdash, &rsa_s, &rsa_em, NULL); |
248 | 0 | TRACE(("leave buf_rsa_verify: ret %d", ret)) |
249 | 0 | return ret; |
250 | 0 | } |
251 | | |
252 | | #endif /* DROPBEAR_SIGNKEY_VERIFY */ |
253 | | |
254 | | /* Sign the data presented with key, writing the signature contents |
255 | | * to the buffer */ |
256 | | void buf_put_rsa_sign(buffer* buf, const dropbear_rsa_key *key, |
257 | 0 | enum signature_type sigtype, const buffer *data_buf) { |
258 | 0 | const char *name = NULL; |
259 | 0 | unsigned int nsize, ssize, namelen = 0; |
260 | 0 | unsigned int i; |
261 | 0 | size_t written; |
262 | 0 | DEF_MP_INT(rsa_s); |
263 | 0 | DEF_MP_INT(rsa_tmp1); |
264 | 0 | DEF_MP_INT(rsa_tmp2); |
265 | 0 | DEF_MP_INT(rsa_tmp3); |
266 | 0 | DEF_MP_INT(rsa_phi_n); |
267 | 0 | DEF_MP_INT(rsa_b_tmp); |
268 | 0 | DEF_MP_INT(rsa_b_rand); |
269 | 0 | DEF_MP_INT(rsa_b_phi); |
270 | 0 | DEF_MP_INT(rsa_b_d); |
271 | | |
272 | 0 | TRACE(("enter buf_put_rsa_sign")) |
273 | 0 | dropbear_assert(key != NULL); |
274 | | |
275 | 0 | m_mp_init_multi(&rsa_s, &rsa_tmp1, &rsa_tmp2, &rsa_tmp3, |
276 | 0 | &rsa_phi_n, &rsa_b_tmp, &rsa_b_rand, &rsa_b_phi, &rsa_b_d, |
277 | 0 | NULL); |
278 | |
|
279 | 0 | rsa_pad_em(key, data_buf, &rsa_tmp1, sigtype); |
280 | | |
281 | | /* the actual signing of the padded data */ |
282 | |
|
283 | 0 | #if DROPBEAR_RSA_BLINDING |
284 | | /* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-rsa-guidance-08 */ |
285 | | |
286 | | /* With base blinding, s = (r^(-1))((em)*r^e)^d mod n */ |
287 | | |
288 | | /* generate the r base blinding value */ |
289 | | /* rsa_tmp2 is r */ |
290 | 0 | gen_random_mpint(key->n, &rsa_tmp2); |
291 | | |
292 | | /* rsa_tmp1 is em */ |
293 | | /* em' = em * r^e mod n */ |
294 | | /* rsa_s used as a temp var*/ |
295 | 0 | if (mp_exptmod(&rsa_tmp2, key->e, key->n, &rsa_s) != MP_OKAY) { |
296 | 0 | dropbear_exit("RSA error"); |
297 | 0 | } |
298 | 0 | if (mp_invmod(&rsa_tmp2, key->n, &rsa_tmp3) != MP_OKAY) { |
299 | 0 | dropbear_exit("RSA error"); |
300 | 0 | } |
301 | 0 | if (mp_mulmod(&rsa_tmp1, &rsa_s, key->n, &rsa_tmp2) != MP_OKAY) { |
302 | 0 | dropbear_exit("RSA error"); |
303 | 0 | } |
304 | | |
305 | | /* exponent blinding, m = c^(d + b*phi(n)) mod n. |
306 | | * b is a 64-bit random value. */ |
307 | 0 | mp_set_u64(&rsa_b_tmp, UINT64_MAX); |
308 | 0 | gen_random_mpint(&rsa_b_tmp, &rsa_b_rand); |
309 | | /* phi(n) = phi(p*q) = phi(p) * phi(q) = (p-1)*(q-1) = n + 1 - p - q |
310 | | * since n = p*q, phi(prime) = prime-1. */ |
311 | 0 | if (mp_add_d(key->n, 1, &rsa_phi_n) != MP_OKAY) { |
312 | 0 | dropbear_exit("RSA error"); |
313 | 0 | } |
314 | | /* rsa_b_d as a temporary */ |
315 | 0 | if (mp_sub(&rsa_phi_n, key->p, &rsa_b_d) != MP_OKAY) { |
316 | 0 | dropbear_exit("RSA error"); |
317 | 0 | } |
318 | 0 | if (mp_sub(&rsa_b_d, key->q, &rsa_phi_n) != MP_OKAY) { |
319 | 0 | dropbear_exit("RSA error"); |
320 | 0 | } |
321 | | |
322 | | /* b*phi(n) */ |
323 | 0 | if (mp_mul(&rsa_b_rand, &rsa_phi_n, &rsa_b_tmp) != MP_OKAY) { |
324 | 0 | dropbear_exit("RSA error"); |
325 | 0 | } |
326 | | /* d + b*phi(n) */ |
327 | 0 | if (mp_add(key->d, &rsa_b_tmp, &rsa_b_d) != MP_OKAY) { |
328 | 0 | dropbear_exit("RSA error"); |
329 | 0 | } |
330 | | |
331 | | /* rsa_tmp2 is em' */ |
332 | | /* s' = (em')^d mod n */ |
333 | 0 | if (mp_exptmod(&rsa_tmp2, &rsa_b_d, key->n, &rsa_tmp1) != MP_OKAY) { |
334 | 0 | dropbear_exit("RSA error"); |
335 | 0 | } |
336 | | |
337 | 0 | m_mp_burn(&rsa_phi_n); |
338 | 0 | m_mp_burn(&rsa_b_tmp); |
339 | 0 | m_mp_burn(&rsa_b_rand); |
340 | 0 | m_mp_burn(&rsa_b_phi); |
341 | 0 | m_mp_burn(&rsa_b_d); |
342 | | |
343 | | /* rsa_tmp1 is s' */ |
344 | | /* rsa_tmp3 is r^(-1) mod n */ |
345 | | /* s = (s')r^(-1) mod n */ |
346 | 0 | if (mp_mulmod(&rsa_tmp1, &rsa_tmp3, key->n, &rsa_s) != MP_OKAY) { |
347 | 0 | dropbear_exit("RSA error"); |
348 | 0 | } |
349 | | |
350 | | #else |
351 | | |
352 | | /* s = em^d mod n */ |
353 | | /* rsa_tmp1 is em */ |
354 | | if (mp_exptmod(&rsa_tmp1, key->d, key->n, &rsa_s) != MP_OKAY) { |
355 | | dropbear_exit("RSA error"); |
356 | | } |
357 | | |
358 | | #endif /* DROPBEAR_RSA_BLINDING */ |
359 | | |
360 | 0 | mp_clear_multi(&rsa_tmp1, &rsa_tmp2, &rsa_tmp3, |
361 | 0 | &rsa_phi_n, &rsa_b_tmp, &rsa_b_rand, &rsa_b_phi, &rsa_b_d, |
362 | 0 | NULL); |
363 | | |
364 | | /* create the signature to return */ |
365 | 0 | name = signature_name_from_type(sigtype, &namelen); |
366 | 0 | buf_putstring(buf, name, namelen); |
367 | |
|
368 | 0 | nsize = mp_ubin_size(key->n); |
369 | | |
370 | | /* string rsa_signature_blob length */ |
371 | 0 | buf_putint(buf, nsize); |
372 | | /* pad out s to same length as n */ |
373 | 0 | ssize = mp_ubin_size(&rsa_s); |
374 | 0 | dropbear_assert(ssize <= nsize); |
375 | 0 | for (i = 0; i < nsize-ssize; i++) { |
376 | 0 | buf_putbyte(buf, 0x00); |
377 | 0 | } |
378 | |
|
379 | 0 | if (mp_to_ubin(&rsa_s, buf_getwriteptr(buf, ssize), ssize, &written) != MP_OKAY) { |
380 | 0 | dropbear_exit("RSA error"); |
381 | 0 | } |
382 | 0 | buf_incrwritepos(buf, written); |
383 | 0 | mp_clear(&rsa_s); |
384 | |
|
385 | | #if defined(DEBUG_RSA) && DEBUG_TRACE |
386 | | if (!debug_trace) { |
387 | | printhex("RSA sig", buf->data, buf->len); |
388 | | } |
389 | | #endif |
390 | | |
391 | |
|
392 | 0 | TRACE(("leave buf_put_rsa_sign")) |
393 | 0 | } |
394 | | |
395 | | /* Creates the message value as expected by PKCS, |
396 | | see rfc8017 section 9.2 */ |
397 | | static void rsa_pad_em(const dropbear_rsa_key * key, |
398 | 0 | const buffer *data_buf, mp_int * rsa_em, enum signature_type sigtype) { |
399 | | /* EM = 0x00 || 0x01 || PS || 0x00 || T |
400 | | PS is padding of 0xff to make EM the size of key->n |
401 | | |
402 | | T is the DER encoding of the hash alg (sha1 or sha256) |
403 | | */ |
404 | | |
405 | | /* From rfc8017 page 46 */ |
406 | 0 | #if DROPBEAR_RSA_SHA1 |
407 | 0 | const unsigned char T_sha1[] = |
408 | 0 | {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, |
409 | 0 | 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}; |
410 | 0 | #endif |
411 | 0 | #if DROPBEAR_RSA_SHA256 |
412 | 0 | const unsigned char T_sha256[] = |
413 | 0 | {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, |
414 | 0 | 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; |
415 | 0 | #endif |
416 | |
|
417 | 0 | int Tlen = 0; |
418 | 0 | const unsigned char *T = NULL; |
419 | 0 | const struct ltc_hash_descriptor *hash_desc = NULL; |
420 | 0 | buffer * rsa_EM = NULL; |
421 | 0 | hash_state hs; |
422 | 0 | unsigned int nsize; |
423 | |
|
424 | 0 | switch (sigtype) { |
425 | 0 | #if DROPBEAR_RSA_SHA1 |
426 | 0 | case DROPBEAR_SIGNATURE_RSA_SHA1: |
427 | 0 | Tlen = sizeof(T_sha1); |
428 | 0 | T = T_sha1; |
429 | 0 | hash_desc = &sha1_desc; |
430 | 0 | break; |
431 | 0 | #endif |
432 | 0 | #if DROPBEAR_RSA_SHA256 |
433 | 0 | case DROPBEAR_SIGNATURE_RSA_SHA256: |
434 | 0 | Tlen = sizeof(T_sha256); |
435 | 0 | T = T_sha256; |
436 | 0 | hash_desc = &sha256_desc; |
437 | 0 | break; |
438 | 0 | #endif |
439 | 0 | default: |
440 | 0 | assert(0); |
441 | 0 | } |
442 | | |
443 | | |
444 | 0 | nsize = mp_ubin_size(key->n); |
445 | |
|
446 | 0 | rsa_EM = buf_new(nsize); |
447 | | /* type byte */ |
448 | 0 | buf_putbyte(rsa_EM, 0x00); |
449 | 0 | buf_putbyte(rsa_EM, 0x01); |
450 | | /* Padding with PS 0xFF bytes */ |
451 | 0 | while(rsa_EM->pos != rsa_EM->size - (1 + Tlen + hash_desc->hashsize)) { |
452 | 0 | buf_putbyte(rsa_EM, 0xff); |
453 | 0 | } |
454 | 0 | buf_putbyte(rsa_EM, 0x00); |
455 | | /* Magic ASN1 stuff */ |
456 | 0 | buf_putbytes(rsa_EM, T, Tlen); |
457 | | |
458 | | /* The hash of the data */ |
459 | 0 | hash_desc->init(&hs); |
460 | 0 | hash_desc->process(&hs, data_buf->data, data_buf->len); |
461 | 0 | hash_desc->done(&hs, buf_getwriteptr(rsa_EM, hash_desc->hashsize)); |
462 | 0 | buf_incrwritepos(rsa_EM, hash_desc->hashsize); |
463 | |
|
464 | 0 | dropbear_assert(rsa_EM->pos == rsa_EM->size); |
465 | | |
466 | | /* Create the mp_int from the encoded bytes */ |
467 | 0 | buf_setpos(rsa_EM, 0); |
468 | 0 | bytes_to_mp(rsa_em, buf_getptr(rsa_EM, rsa_EM->size), |
469 | 0 | rsa_EM->size); |
470 | 0 | buf_free(rsa_EM); |
471 | 0 | } |
472 | | |
473 | | #endif /* DROPBEAR_RSA */ |