aboutsummaryrefslogtreecommitdiff
path: root/src/util/rsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/rsa.c')
-rw-r--r--src/util/rsa.c925
1 files changed, 925 insertions, 0 deletions
diff --git a/src/util/rsa.c b/src/util/rsa.c
new file mode 100644
index 000000000..cde56be9e
--- /dev/null
+++ b/src/util/rsa.c
@@ -0,0 +1,925 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file util/rsa.c
19 * @brief RSA key management utilities. Most of the code here is taken from
20 * gnunet-0.9.5a
21 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
22 *
23 * Authors of the gnunet code:
24 * Christian Grothoff
25 * Krista Bennett
26 * Gerd Knorr <kraxel@bytesex.org>
27 * Ioana Patrascu
28 * Tzvetan Horozov
29 */
30
31#include "platform.h"
32#include "gcrypt.h"
33#include "gnunet/gnunet_util_lib.h"
34#include "taler_rsa.h"
35
36
37
38#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
39
40#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
41
42#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
43
44/**
45 * Log an error message at log-level 'level' that indicates
46 * a failure of the command 'cmd' with the message given
47 * by gcry_strerror(rc).
48 */
49#define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0)
50
51/**
52 * Shorthand to cleanup non null mpi data types
53 */
54#define mpi_release_non_null(mpi) \
55 if (NULL != mpi) gcry_mpi_release (mpi);
56
57/**
58 * The private information of an RSA key pair.
59 * NOTE: this must match the definition in crypto_ksk.c and gnunet-rsa.c!
60 */
61struct TALER_RSA_PrivateKey
62{
63 /**
64 * Libgcrypt S-expression for the ECC key.
65 */
66 gcry_sexp_t sexp;
67};
68
69
70/**
71 * Extract values from an S-expression.
72 *
73 * @param array where to store the result(s)
74 * @param sexp S-expression to parse
75 * @param topname top-level name in the S-expression that is of interest
76 * @param elems names of the elements to extract
77 * @return 0 on success
78 */
79static int
80key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname,
81 const char *elems)
82{
83 gcry_sexp_t list;
84 gcry_sexp_t l2;
85 const char *s;
86 unsigned int i;
87 unsigned int idx;
88
89 if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
90 return 1;
91 l2 = gcry_sexp_cadr (list);
92 gcry_sexp_release (list);
93 list = l2;
94 if (! list)
95 return 2;
96 idx = 0;
97 for (s = elems; *s; s++, idx++)
98 {
99 if (! (l2 = gcry_sexp_find_token (list, s, 1)))
100 {
101 for (i = 0; i < idx; i++)
102 {
103 gcry_free (array[i]);
104 array[i] = NULL;
105 }
106 gcry_sexp_release (list);
107 return 3; /* required parameter not found */
108 }
109 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
110 gcry_sexp_release (l2);
111 if (! array[idx])
112 {
113 for (i = 0; i < idx; i++)
114 {
115 gcry_free (array[i]);
116 array[i] = NULL;
117 }
118 gcry_sexp_release (list);
119 return 4; /* required parameter is invalid */
120 }
121 }
122 gcry_sexp_release (list);
123 return 0;
124}
125
126/**
127 * If target != size, move target bytes to the
128 * end of the size-sized buffer and zero out the
129 * first target-size bytes.
130 *
131 * @param buf original buffer
132 * @param size number of bytes in the buffer
133 * @param target target size of the buffer
134 */
135static void
136adjust (unsigned char *buf, size_t size, size_t target)
137{
138 if (size < target)
139 {
140 memmove (&buf[target - size], buf, size);
141 memset (buf, 0, target - size);
142 }
143}
144
145
146/**
147 * Create a new private key. Caller must free return value.
148 *
149 * @return fresh private key
150 */
151struct TALER_RSA_PrivateKey *
152TALER_RSA_key_create ()
153{
154 struct TALER_RSA_PrivateKey *ret;
155 gcry_sexp_t s_key;
156 gcry_sexp_t s_keyparam;
157
158 GNUNET_assert (0 ==
159 gcry_sexp_build (&s_keyparam, NULL,
160 "(genkey(rsa(nbits %d)(rsa-use-e 3:257)))",
161 2048));
162 GNUNET_assert (0 == gcry_pk_genkey (&s_key, s_keyparam));
163 gcry_sexp_release (s_keyparam);
164#if EXTRA_CHECKS
165 GNUNET_assert (0 == gcry_pk_testkey (s_key));
166#endif
167 ret = GNUNET_malloc (sizeof (struct TALER_RSA_PrivateKey));
168 ret->sexp = s_key;
169 return ret;
170}
171
172
173/**
174 * Free memory occupied by the private key.
175 *
176 * @param key pointer to the memory to free
177 */
178void
179TALER_RSA_key_free (struct TALER_RSA_PrivateKey *key)
180{
181 gcry_sexp_release (key->sexp);
182 GNUNET_free (key);
183}
184
185
186/**
187 * Encode the private key in a format suitable for
188 * storing it into a file.
189 * @return encoding of the private key
190 */
191struct TALER_RSA_PrivateKeyBinaryEncoded *
192TALER_RSA_encode_key (const struct TALER_RSA_PrivateKey *hostkey)
193{
194 struct TALER_RSA_PrivateKeyBinaryEncoded *retval;
195 gcry_mpi_t pkv[6];
196 void *pbu[6];
197 size_t sizes[6];
198 int rc;
199 int i;
200 int size;
201
202#if EXTRA_CHECKS
203 if (gcry_pk_testkey (hostkey->sexp))
204 {
205 GNUNET_break (0);
206 return NULL;
207 }
208#endif
209
210 memset (pkv, 0, sizeof (gcry_mpi_t) * 6);
211 rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "nedpqu");
212 if (rc)
213 rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "nedpqu");
214 if (rc)
215 rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "nedpq");
216 if (rc)
217 rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "nedpq");
218 if (rc)
219 rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "ned");
220 if (rc)
221 rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "ned");
222 GNUNET_assert (0 == rc);
223 size = sizeof (struct TALER_RSA_PrivateKeyBinaryEncoded);
224 for (i = 0; i < 6; i++)
225 {
226 if (NULL != pkv[i])
227 {
228 GNUNET_assert (0 ==
229 gcry_mpi_aprint (GCRYMPI_FMT_USG,
230 (unsigned char **) &pbu[i], &sizes[i],
231 pkv[i]));
232 size += sizes[i];
233 }
234 else
235 {
236 pbu[i] = NULL;
237 sizes[i] = 0;
238 }
239 }
240 GNUNET_assert (size < 65536);
241 retval = GNUNET_malloc (size);
242 retval->len = htons (size);
243 i = 0;
244 retval->sizen = htons (sizes[0]);
245 memcpy (&((char *) (&retval[1]))[i], pbu[0], sizes[0]);
246 i += sizes[0];
247 retval->sizee = htons (sizes[1]);
248 memcpy (&((char *) (&retval[1]))[i], pbu[1], sizes[1]);
249 i += sizes[1];
250 retval->sized = htons (sizes[2]);
251 memcpy (&((char *) (&retval[1]))[i], pbu[2], sizes[2]);
252 i += sizes[2];
253 /* swap p and q! */
254 retval->sizep = htons (sizes[4]);
255 memcpy (&((char *) (&retval[1]))[i], pbu[4], sizes[4]);
256 i += sizes[4];
257 retval->sizeq = htons (sizes[3]);
258 memcpy (&((char *) (&retval[1]))[i], pbu[3], sizes[3]);
259 i += sizes[3];
260 retval->sizedmp1 = htons (0);
261 retval->sizedmq1 = htons (0);
262 memcpy (&((char *) (&retval[1]))[i], pbu[5], sizes[5]);
263 for (i = 0; i < 6; i++)
264 {
265 if (pkv[i] != NULL)
266 gcry_mpi_release (pkv[i]);
267 if (pbu[i] != NULL)
268 free (pbu[i]);
269 }
270 return retval;
271}
272
273
274/**
275 * Extract the public key of the given private key.
276 *
277 * @param priv the private key
278 * @param pub where to write the public key
279 */
280void
281TALER_RSA_key_get_public (const struct TALER_RSA_PrivateKey *priv,
282 struct TALER_RSA_PublicKeyBinaryEncoded *pub)
283{
284 gcry_mpi_t skey[2];
285 size_t size;
286 int rc;
287
288 rc = key_from_sexp (skey, priv->sexp, "public-key", "ne");
289 if (0 != rc)
290 rc = key_from_sexp (skey, priv->sexp, "private-key", "ne");
291 if (0 != rc)
292 rc = key_from_sexp (skey, priv->sexp, "rsa", "ne");
293 GNUNET_assert (0 == rc);
294 pub->len =
295 htons (sizeof (struct TALER_RSA_PublicKeyBinaryEncoded) -
296 sizeof (pub->padding));
297 pub->sizen = htons (TALER_RSA_DATA_ENCODING_LENGTH);
298 pub->padding = 0;
299 size = TALER_RSA_DATA_ENCODING_LENGTH;
300 GNUNET_assert (0 ==
301 gcry_mpi_print (GCRYMPI_FMT_USG, &pub->key[0], size, &size,
302 skey[0]));
303 adjust (&pub->key[0], size, TALER_RSA_DATA_ENCODING_LENGTH);
304 size = TALER_RSA_KEY_LENGTH - TALER_RSA_DATA_ENCODING_LENGTH;
305 GNUNET_assert (0 ==
306 gcry_mpi_print (GCRYMPI_FMT_USG,
307 &pub->key
308 [TALER_RSA_DATA_ENCODING_LENGTH], size,
309 &size, skey[1]));
310 adjust (&pub->key[TALER_RSA_DATA_ENCODING_LENGTH], size,
311 TALER_RSA_KEY_LENGTH -
312 TALER_RSA_DATA_ENCODING_LENGTH);
313 gcry_mpi_release (skey[0]);
314 gcry_mpi_release (skey[1]);
315}
316
317
318/**
319 * Decode the private key from the data-format back
320 * to the "normal", internal format.
321 *
322 * @param buf the buffer where the private key data is stored
323 * @param len the length of the data in 'buffer'
324 * @return NULL on error
325 */
326struct TALER_RSA_PrivateKey *
327TALER_RSA_decode_key (const char *buf, uint16_t len)
328{
329 struct TALER_RSA_PrivateKey *ret;
330 const struct TALER_RSA_PrivateKeyBinaryEncoded *encoding =
331 (const struct TALER_RSA_PrivateKeyBinaryEncoded *) buf;
332 gcry_sexp_t res;
333 gcry_mpi_t n;
334 gcry_mpi_t e;
335 gcry_mpi_t d;
336 gcry_mpi_t p;
337 gcry_mpi_t q;
338 gcry_mpi_t u;
339 int rc;
340 size_t size;
341 size_t pos;
342 uint16_t enc_len;
343 size_t erroff;
344
345 enc_len = ntohs (encoding->len);
346 if (len != enc_len)
347 return NULL;
348
349 pos = 0;
350 size = ntohs (encoding->sizen);
351 rc = gcry_mpi_scan (&n, GCRYMPI_FMT_USG,
352 &((const unsigned char *) (&encoding[1]))[pos], size,
353 &size);
354 pos += ntohs (encoding->sizen);
355 if (0 != rc)
356 {
357 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
358 return NULL;
359 }
360 size = ntohs (encoding->sizee);
361 rc = gcry_mpi_scan (&e, GCRYMPI_FMT_USG,
362 &((const unsigned char *) (&encoding[1]))[pos], size,
363 &size);
364 pos += ntohs (encoding->sizee);
365 if (0 != rc)
366 {
367 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
368 gcry_mpi_release (n);
369 return NULL;
370 }
371 size = ntohs (encoding->sized);
372 rc = gcry_mpi_scan (&d, GCRYMPI_FMT_USG,
373 &((const unsigned char *) (&encoding[1]))[pos], size,
374 &size);
375 pos += ntohs (encoding->sized);
376 if (0 != rc)
377 {
378 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
379 gcry_mpi_release (n);
380 gcry_mpi_release (e);
381 return NULL;
382 }
383 /* swap p and q! */
384 size = ntohs (encoding->sizep);
385 if (size > 0)
386 {
387 rc = gcry_mpi_scan (&q, GCRYMPI_FMT_USG,
388 &((const unsigned char *) (&encoding[1]))[pos], size,
389 &size);
390 pos += ntohs (encoding->sizep);
391 if (0 != rc)
392 {
393 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
394 gcry_mpi_release (n);
395 gcry_mpi_release (e);
396 gcry_mpi_release (d);
397 return NULL;
398 }
399 }
400 else
401 q = NULL;
402 size = ntohs (encoding->sizeq);
403 if (size > 0)
404 {
405 rc = gcry_mpi_scan (&p, GCRYMPI_FMT_USG,
406 &((const unsigned char *) (&encoding[1]))[pos], size,
407 &size);
408 pos += ntohs (encoding->sizeq);
409 if (0 != rc)
410 {
411 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
412 gcry_mpi_release (n);
413 gcry_mpi_release (e);
414 gcry_mpi_release (d);
415 if (NULL != q)
416 gcry_mpi_release (q);
417 return NULL;
418 }
419 }
420 else
421 p = NULL;
422 pos += ntohs (encoding->sizedmp1);
423 pos += ntohs (encoding->sizedmq1);
424 size =
425 ntohs (encoding->len) - sizeof (struct TALER_RSA_PrivateKeyBinaryEncoded) - pos;
426 if (size > 0)
427 {
428 rc = gcry_mpi_scan (&u, GCRYMPI_FMT_USG,
429 &((const unsigned char *) (&encoding[1]))[pos], size,
430 &size);
431 if (0 != rc)
432 {
433 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
434 gcry_mpi_release (n);
435 gcry_mpi_release (e);
436 gcry_mpi_release (d);
437 if (NULL != p)
438 gcry_mpi_release (p);
439 if (NULL != q)
440 gcry_mpi_release (q);
441 return NULL;
442 }
443 }
444 else
445 u = NULL;
446
447 if ((NULL != p) && (NULL != q) && (NULL != u))
448 {
449 rc = gcry_sexp_build (&res, &erroff,
450 "(private-key(rsa(n %m)(e %m)(d %m)(p %m)(q %m)(u %m)))",
451 n, e, d, p, q, u);
452 }
453 else
454 {
455 if ((NULL != p) && (NULL != q))
456 {
457 rc = gcry_sexp_build (&res, &erroff,
458 "(private-key(rsa(n %m)(e %m)(d %m)(p %m)(q %m)))",
459 n, e, d, p, q);
460 }
461 else
462 {
463 rc = gcry_sexp_build (&res, &erroff,
464 "(private-key(rsa(n %m)(e %m)(d %m)))", n, e, d);
465 }
466 }
467 gcry_mpi_release (n);
468 gcry_mpi_release (e);
469 gcry_mpi_release (d);
470 if (NULL != p)
471 gcry_mpi_release (p);
472 if (NULL != q)
473 gcry_mpi_release (q);
474 if (NULL != u)
475 gcry_mpi_release (u);
476
477 if (0 != rc)
478 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
479 if (0 != (rc = gcry_pk_testkey (res)))
480 {
481 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
482 return NULL;
483 }
484 ret = GNUNET_malloc (sizeof (struct TALER_RSA_PrivateKey));
485 ret->sexp = res;
486 return ret;
487}
488
489
490/**
491 * Convert a public key to a string.
492 *
493 * @param pub key to convert
494 * @return string representing 'pub'
495 */
496char *
497TALER_RSA_public_key_to_string (const struct TALER_RSA_PublicKeyBinaryEncoded *pub)
498{
499 char *pubkeybuf;
500 size_t keylen = (sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)) * 8;
501 char *end;
502
503 if (keylen % 5 > 0)
504 keylen += 5 - keylen % 5;
505 keylen /= 5;
506 pubkeybuf = GNUNET_malloc (keylen + 1);
507 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
508 sizeof (struct TALER_RSA_PublicKeyBinaryEncoded),
509 pubkeybuf,
510 keylen);
511 if (NULL == end)
512 {
513 GNUNET_free (pubkeybuf);
514 return NULL;
515 }
516 *end = '\0';
517 return pubkeybuf;
518}
519
520
521/**
522 * Convert a string representing a public key to a public key.
523 *
524 * @param enc encoded public key
525 * @param enclen number of bytes in enc (without 0-terminator)
526 * @param pub where to store the public key
527 * @return GNUNET_OK on success
528 */
529int
530TALER_RSA_public_key_from_string (const char *enc,
531 size_t enclen,
532 struct TALER_RSA_PublicKeyBinaryEncoded *pub)
533{
534 size_t keylen = (sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)) * 8;
535
536 if (keylen % 5 > 0)
537 keylen += 5 - keylen % 5;
538 keylen /= 5;
539 if (enclen != keylen)
540 return GNUNET_SYSERR;
541
542 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
543 (unsigned char*) pub,
544 sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)))
545 return GNUNET_SYSERR;
546 if ( (ntohs (pub->len) != sizeof (struct TALER_RSA_PublicKeyBinaryEncoded)) ||
547 (ntohs (pub->padding) != 0) ||
548 (ntohs (pub->sizen) != TALER_RSA_DATA_ENCODING_LENGTH) )
549 return GNUNET_SYSERR;
550 return GNUNET_OK;
551}
552
553
554/**
555 * Convert the data specified in the given purpose argument to an
556 * S-expression suitable for signature operations.
557 *
558 * @param ptr pointer to the data to convert
559 * @param size the size of the data
560 * @return converted s-expression
561 */
562static gcry_sexp_t
563data_to_sexp (const void *ptr, size_t size)
564{
565 gcry_mpi_t value;
566 gcry_sexp_t data;
567
568 value = NULL;
569 data = NULL;
570 GNUNET_assert (0 == gcry_mpi_scan (&value, GCRYMPI_FMT_USG, ptr, size, NULL));
571 GNUNET_assert (0 == gcry_sexp_build (&data, NULL, "(data (flags raw) (value %M))", value));
572 gcry_mpi_release (value);
573 return data;
574}
575
576
577/**
578 * Sign the given hash block.
579 *
580 * @param key private key to use for the signing
581 * @param hash the block containing the hash of the message to sign
582 * @param hash_size the size of the hash block
583 * @param sig where to write the signature
584 * @return GNUNET_SYSERR on error, GNUNET_OK on success
585 */
586int
587TALER_RSA_sign (const struct TALER_RSA_PrivateKey *key,
588 const void *hash,
589 size_t hash_size,
590 struct TALER_RSA_Signature *sig)
591{
592 gcry_sexp_t result;
593 gcry_sexp_t data;
594 size_t ssize;
595 gcry_mpi_t rval;
596
597 data = data_to_sexp (hash, hash_size);
598 GNUNET_assert (0 == gcry_pk_sign (&result, data, key->sexp));
599 gcry_sexp_release (data);
600 GNUNET_assert (0 == key_from_sexp (&rval, result, "rsa", "s"));
601 gcry_sexp_release (result);
602 ssize = sizeof (struct TALER_RSA_Signature);
603 GNUNET_assert (0 ==
604 gcry_mpi_print (GCRYMPI_FMT_USG, (unsigned char *) sig, ssize,
605 &ssize, rval));
606 gcry_mpi_release (rval);
607 adjust (sig->sig, ssize, sizeof (struct TALER_RSA_Signature));
608 return GNUNET_OK;
609}
610
611
612/**
613 * Convert the given public key from the network format to the
614 * S-expression that can be used by libgcrypt.
615 *
616 * @param publicKey public key to decode
617 * @return NULL on error
618 */
619static gcry_sexp_t
620decode_public_key (const struct TALER_RSA_PublicKeyBinaryEncoded *publicKey)
621{
622 gcry_sexp_t result;
623 gcry_mpi_t n;
624 gcry_mpi_t e;
625 size_t size;
626 size_t erroff;
627 int rc;
628
629 if ((ntohs (publicKey->sizen) != TALER_RSA_DATA_ENCODING_LENGTH) ||
630 (ntohs (publicKey->len) !=
631 sizeof (struct TALER_RSA_PublicKeyBinaryEncoded) -
632 sizeof (publicKey->padding)))
633 {
634 GNUNET_break (0);
635 return NULL;
636 }
637 size = TALER_RSA_DATA_ENCODING_LENGTH;
638 if (0 != (rc = gcry_mpi_scan (&n, GCRYMPI_FMT_USG, &publicKey->key[0], size, &size)))
639 {
640 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
641 return NULL;
642 }
643 size = TALER_RSA_KEY_LENGTH - TALER_RSA_DATA_ENCODING_LENGTH;
644 if (0 != (rc = gcry_mpi_scan (&e, GCRYMPI_FMT_USG,
645 &publicKey->key[TALER_RSA_DATA_ENCODING_LENGTH],
646 size, &size)))
647 {
648 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
649 gcry_mpi_release (n);
650 return NULL;
651 }
652 rc = gcry_sexp_build (&result, &erroff, "(public-key(rsa(n %m)(e %m)))", n,
653 e);
654 gcry_mpi_release (n);
655 gcry_mpi_release (e);
656 if (0 != rc)
657 {
658 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); /* erroff gives more info */
659 return NULL;
660 }
661 return result;
662}
663
664
665/**
666 * Verify signature with the given hash.
667 *
668 * @param hash the hash code to verify against the signature
669 * @param sig signature that is being validated
670 * @param publicKey public key of the signer
671 * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid
672 */
673int
674TALER_RSA_hash_verify (const struct GNUNET_HashCode *hash,
675 const struct TALER_RSA_Signature *sig,
676 const struct TALER_RSA_PublicKeyBinaryEncoded *publicKey)
677{
678 gcry_sexp_t data;
679 gcry_sexp_t sigdata;
680 size_t size;
681 gcry_mpi_t val;
682 gcry_sexp_t psexp;
683 size_t erroff;
684 int rc;
685
686 size = sizeof (struct TALER_RSA_Signature);
687 GNUNET_assert (0 ==
688 gcry_mpi_scan (&val, GCRYMPI_FMT_USG,
689 (const unsigned char *) sig, size, &size));
690 GNUNET_assert (0 ==
691 gcry_sexp_build (&sigdata, &erroff, "(sig-val(rsa(s %m)))",
692 val));
693 gcry_mpi_release (val);
694 data = data_to_sexp (hash, sizeof (struct GNUNET_HashCode));
695 if (! (psexp = decode_public_key (publicKey)))
696 {
697 gcry_sexp_release (data);
698 gcry_sexp_release (sigdata);
699 return GNUNET_SYSERR;
700 }
701 rc = gcry_pk_verify (sigdata, data, psexp);
702 gcry_sexp_release (psexp);
703 gcry_sexp_release (data);
704 gcry_sexp_release (sigdata);
705 if (rc)
706 {
707 LOG (GNUNET_ERROR_TYPE_WARNING,
708 _("RSA signature verification failed at %s:%d: %s\n"), __FILE__,
709 __LINE__, gcry_strerror (rc));
710 return GNUNET_SYSERR;
711 }
712 return GNUNET_OK;
713}
714
715
716/**
717 * Verify signature on the given message
718 *
719 * @param msg the message
720 * @param size the size of the message
721 * @param sig signature that is being validated
722 * @param publicKey public key of the signer
723 * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid
724 */
725int
726TALER_RSA_verify (const void *msg, size_t size,
727 const struct TALER_RSA_Signature *sig,
728 const struct TALER_RSA_PublicKeyBinaryEncoded *publicKey)
729{
730 struct GNUNET_HashCode hash;
731
732 GNUNET_CRYPTO_hash (msg, size, &hash);
733 return TALER_RSA_hash_verify (&hash, sig, publicKey);
734}
735
736/**
737 * The blinding key is equal in length to the RSA modulus
738 */
739#define TALER_RSA_BLINDING_KEY_LEN TALER_RSA_DATA_ENCODING_LENGTH
740
741struct TALER_RSA_BlindingKey
742{
743 /**
744 * The blinding factor
745 */
746 gcry_mpi_t r;
747};
748
749struct TALER_RSA_BlindingKey *
750TALER_RSA_blinding_key_create ()
751{
752 struct TALER_RSA_BlindingKey *blind;
753
754 blind = GNUNET_new (struct TALER_RSA_BlindingKey);
755 blind->r = gcry_mpi_new (TALER_RSA_BLINDING_KEY_LEN * 8);
756 gcry_mpi_randomize (blind->r, TALER_RSA_BLINDING_KEY_LEN * 8, GCRY_STRONG_RANDOM);
757 return blind;
758}
759
760
761void
762TALER_RSA_blinding_key_destroy (struct TALER_RSA_BlindingKey *bkey)
763{
764 gcry_mpi_release (bkey->r);
765 GNUNET_free (bkey);
766}
767
768
769struct TALER_RSA_BlindedSignaturePurpose *
770TALER_RSA_message_blind (const void *msg, size_t size,
771 struct TALER_RSA_BlindingKey *bkey,
772 struct TALER_RSA_PublicKeyBinaryEncoded *pkey)
773{
774 struct TALER_RSA_BlindedSignaturePurpose *bsp;
775 struct GNUNET_HashCode hash;
776 gcry_sexp_t psexp;
777 gcry_mpi_t data;
778 gcry_mpi_t skey[2];
779 gcry_mpi_t r_e;
780 gcry_mpi_t data_r_e;
781 size_t rsize;
782 gcry_error_t rc;
783 int ret;
784
785 bsp = NULL;
786 psexp = NULL;
787 data = NULL;
788 skey[0] = skey[1] = NULL;
789 r_e = NULL;
790 data_r_e = NULL;
791 rsize = 0;
792 rc = 0;
793 ret = 0;
794 if (! (psexp = decode_public_key (pkey)))
795 return NULL;
796 ret = key_from_sexp (skey, psexp, "public-key", "ne");
797 if (0 != ret)
798 ret = key_from_sexp (skey, psexp, "rsa", "ne");
799 gcry_sexp_release (psexp);
800 psexp = NULL;
801 GNUNET_assert (0 == ret);
802 GNUNET_CRYPTO_hash (msg, size, &hash);
803 if (0 != (rc=gcry_mpi_scan (&data, GCRYMPI_FMT_USG,
804 (const unsigned char *) msg, size, &rsize)))
805 {
806 LOG_GCRY (GNUNET_ERROR_TYPE_WARNING, "gcry_mpi_scan", rc);
807 goto cleanup;
808 }
809 r_e = gcry_mpi_new (0);
810 gcry_mpi_powm (r_e, bkey->r,
811 skey[1], /* e */
812 skey[0]); /* n */
813
814 data_r_e = gcry_mpi_new (0);
815 gcry_mpi_mulm (data_r_e, data, r_e, skey[0]);
816
817 bsp = GNUNET_new (struct TALER_RSA_BlindedSignaturePurpose);
818 rc = gcry_mpi_print (GCRYMPI_FMT_USG,
819 (unsigned char *) bsp,
820 sizeof (struct TALER_RSA_BlindedSignaturePurpose),
821 &rsize,
822 data_r_e);
823 GNUNET_assert (0 == rc);
824 adjust ((unsigned char *) bsp, rsize,
825 sizeof (struct TALER_RSA_BlindedSignaturePurpose));
826
827 cleanup:
828 if (NULL != psexp) gcry_sexp_release (psexp);
829 mpi_release_non_null (skey[0]);
830 mpi_release_non_null (skey[1]);
831 mpi_release_non_null (data);
832 mpi_release_non_null (r_e);
833 mpi_release_non_null (data_r_e);
834 return bsp;
835}
836
837
838int
839TALER_RSA_unblind (struct TALER_RSA_Signature *sig,
840 struct TALER_RSA_BlindingKey *bkey,
841 struct TALER_RSA_PublicKeyBinaryEncoded *pkey)
842{
843 gcry_sexp_t psexp;
844 gcry_mpi_t skey;
845 gcry_mpi_t sigval;
846 gcry_mpi_t r_inv;
847 gcry_mpi_t ubsig;
848 size_t rsize;
849 gcry_error_t rc;
850 int ret;
851
852 psexp = NULL;
853 skey = NULL;
854 sigval = NULL;
855 r_inv = NULL;
856 ubsig = NULL;
857 rsize = 0;
858 rc = 0;
859 ret = GNUNET_SYSERR;
860 if (! (psexp = decode_public_key (pkey)))
861 return GNUNET_SYSERR;
862 ret = key_from_sexp (&skey, psexp, "public-key", "n");
863 if (0 != ret)
864 ret = key_from_sexp (&skey, psexp, "rsa", "n");
865 gcry_sexp_release (psexp);
866 psexp = NULL;
867 if (0 != (rc = gcry_mpi_scan (&sigval, GCRYMPI_FMT_USG,
868 (const unsigned char *) sig,
869 sizeof (struct TALER_RSA_Signature),
870 &rsize)))
871 {
872 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
873 goto cleanup;
874 }
875 r_inv = gcry_mpi_new (0);
876 GNUNET_assert (1 == gcry_mpi_invm (r_inv, bkey->r, skey)); /* n: skey */
877 ubsig = gcry_mpi_new (0);
878 gcry_mpi_mulm (ubsig, sigval, r_inv, skey);
879 rc = gcry_mpi_print (GCRYMPI_FMT_USG,
880 (unsigned char *) sig,
881 sizeof (struct TALER_RSA_Signature),
882 &rsize,
883 ubsig);
884 GNUNET_assert (0 == rc);
885 adjust ((unsigned char *) sig, rsize, sizeof (struct TALER_RSA_Signature));
886 ret = GNUNET_OK;
887
888 cleanup:
889 if (NULL != psexp) gcry_sexp_release (psexp);
890 mpi_release_non_null (skey);
891 mpi_release_non_null (sigval);
892 mpi_release_non_null (r_inv);
893 mpi_release_non_null (ubsig);
894 return ret;
895}
896
897
898/**
899 * Encode a blinding key
900 *
901 * @param bkey the blinding key to encode
902 * @param bkey_enc where to store the encoded binary key
903 * @return #GNUNET_OK upon successful encoding; #GNUNET_SYSERR upon failure
904 */
905int
906TALER_RSA_blinding_key_encode (struct TALER_RSA_BlindingKey *bkey,
907 struct TALER_RSA_BlindingKeyBinaryEncoded *bkey_enc)
908{
909 GNUNET_abort (); /* FIXME: not implemented */
910}
911
912
913/**
914 * Decode a blinding key from its encoded form
915 *
916 * @param bkey_enc the encoded blinding key
917 * @return the decoded blinding key; NULL upon error
918 */
919struct TALER_RSA_BlindingKey *
920TALER_RSA_blinding_key_decode (struct TALER_RSA_BlindingKeyBinaryEncoded *bkey_enc)
921{
922 GNUNET_abort (); /* FIXME: not implemented */
923}
924
925/* end of util/rsa.c */