5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2007 - 2008 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 #include "silccrypto.h"
24 /**************************** OpenPGP PKCS API ******************************/
26 /* Get algorithm context */
28 SILC_PKCS_GET_ALGORITHM(silc_pkcs_pgp_get_algorithm)
30 SilcPGPPublicKey pubkey = public_key;
34 /* Import PGP public key file */
36 SILC_PKCS_IMPORT_PUBLIC_KEY_FILE(silc_pkcs_pgp_import_public_key_file)
40 unsigned char *data = NULL;
41 SilcPGPPublicKey pubkey;
43 SILC_LOG_DEBUG(("Parsing OpenPGP public key file"));
49 case SILC_PKCS_FILE_BIN:
52 case SILC_PKCS_FILE_BASE64:
53 data = silc_pgp_dearmor(filedata, filedata_len, &filedata_len);
60 /* Parse PGP packets */
61 if (!silc_pgp_packet_decode(filedata, filedata_len, NULL, &list)) {
67 /* Parse the public key */
68 ret = silc_pgp_public_key_decode(&list, &pubkey);
71 *ret_alg = pubkey->pkcs;
73 *ret_public_key = pubkey;
76 silc_pgp_packet_free_list(&list);
81 /* Import OpenPGP public key packet (OpenPGP certificate). */
83 SILC_PKCS_IMPORT_PUBLIC_KEY(silc_pkcs_pgp_import_public_key)
85 SilcPGPPublicKey pubkey;
88 pubkey = silc_calloc(1, sizeof(*pubkey));
92 ret = silc_pgp_packet_public_key_decode(key, key_len, pubkey);
95 *ret_alg = pubkey->pkcs;
97 *ret_public_key = pubkey;
105 /* Export PGP public key file */
107 SILC_PKCS_EXPORT_PUBLIC_KEY_FILE(silc_pkcs_pgp_export_public_key_file)
112 /* Export OpenPGP public key */
114 SILC_PKCS_EXPORT_PUBLIC_KEY(silc_pkcs_pgp_export_public_key)
119 /* Return public key length in bits */
121 SILC_PKCS_PUBLIC_KEY_BITLEN(silc_pkcs_pgp_public_key_bitlen)
124 SilcPGPPublicKey pubkey = public_key;
125 return pubkey->pkcs->public_key_bitlen(pubkey->pkcs, pubkey->public_key);
128 /* Copy public key */
130 SILC_PKCS_PUBLIC_KEY_COPY(silc_pkcs_pgp_public_key_copy)
132 SilcPGPPublicKey pubkey = public_key, new_pubkey, p;
133 SilcPGPPacket packet;
135 new_pubkey = silc_calloc(1, sizeof(*new_pubkey));
139 if (pubkey->subkeys) {
140 new_pubkey->subkeys = silc_dlist_init();
141 if (!new_pubkey->subkeys) {
142 silc_free(new_pubkey);
146 silc_dlist_start(pubkey->subkeys);
147 while ((p = silc_dlist_get(pubkey->subkeys))) {
148 p = silc_pkcs_pgp_public_key_copy(pkcs, p);
150 silc_dlist_add(new_pubkey->subkeys, p);
154 silc_list_init(new_pubkey->packets, struct SilcPGPPacketStruct, next);
155 silc_list_start(pubkey->packets);
156 while ((packet = silc_list_get(pubkey->packets))) {
157 packet = silc_pgp_packet_copy(packet);
159 silc_free(new_pubkey);
162 silc_list_add(new_pubkey->packets, packet);
165 memcpy(new_pubkey->key_id, pubkey->key_id, sizeof(pubkey->key_id));
166 memcpy(new_pubkey->fingerprint, pubkey->fingerprint,
167 sizeof(pubkey->fingerprint));
168 new_pubkey->created = pubkey->created;
169 new_pubkey->valid = pubkey->valid;
170 new_pubkey->version = pubkey->version;
171 new_pubkey->algorithm = pubkey->algorithm;
173 new_pubkey->public_key = pubkey->pkcs->public_key_copy(pubkey->pkcs,
175 if (!new_pubkey->public_key) {
176 silc_free(new_pubkey);
183 /* Compares public keys */
185 SILC_PKCS_PUBLIC_KEY_COMPARE(silc_pkcs_pgp_public_key_compare)
187 SilcPGPPublicKey k1 = key1, k2 = key2;
189 if (k1->version != k2->version)
191 if (k1->created != k2->created)
193 if (k1->valid != k2->valid)
195 if (k1->algorithm != k2->algorithm)
197 if (memcmp(k1->key_id, k2->key_id, sizeof(k1->key_id)))
199 if (memcmp(k1->fingerprint, k2->fingerprint, sizeof(k1->fingerprint)))
202 return k1->pkcs->public_key_compare(k1->pkcs,
203 k1->public_key, k2->public_key);
206 /* Free public key */
208 SILC_PKCS_PUBLIC_KEY_FREE(silc_pkcs_pgp_public_key_free)
210 silc_pgp_public_key_free(public_key);
213 /* Import PGP private key file */
215 SILC_PKCS_IMPORT_PRIVATE_KEY_FILE(silc_pkcs_pgp_import_private_key_file)
219 unsigned char *data = NULL;
220 SilcPGPPrivateKey privkey;
222 SILC_LOG_DEBUG(("Parsing OpenPGP private key file"));
224 if (!ret_private_key)
228 case SILC_PKCS_FILE_BIN:
231 case SILC_PKCS_FILE_BASE64:
232 data = silc_pgp_dearmor(filedata, filedata_len, &filedata_len);
239 /* Parse PGP packets */
240 if (!silc_pgp_packet_decode(filedata, filedata_len, NULL, &list)) {
246 /* Parse the private key */
247 ret = silc_pgp_private_key_decode(&list, passphrase, passphrase_len,
251 *ret_alg = privkey->public_key->pkcs;
253 *ret_private_key = privkey;
256 silc_pgp_packet_free_list(&list);
261 /* Import OpenPGP private key */
263 SILC_PKCS_IMPORT_PRIVATE_KEY(silc_pkcs_pgp_import_private_key)
265 SilcPGPPrivateKey privkey;
268 privkey = silc_calloc(1, sizeof(*privkey));
272 ret = silc_pgp_packet_private_key_decode(key, key_len, passphrase,
273 passphrase_len, privkey);
276 *ret_alg = privkey->public_key->pkcs;
278 *ret_private_key = privkey;
286 /* Export PGP private key file */
288 SILC_PKCS_EXPORT_PRIVATE_KEY_FILE(silc_pkcs_pgp_export_private_key_file)
293 /* Export OpenPGP private key */
295 SILC_PKCS_EXPORT_PRIVATE_KEY(silc_pkcs_pgp_export_private_key)
300 /* Returns key length in bits */
302 SILC_PKCS_PRIVATE_KEY_BITLEN(silc_pkcs_pgp_private_key_bitlen)
304 SilcPGPPrivateKey privkey = private_key;
305 return silc_pkcs_pgp_public_key_bitlen(pkcs, privkey->public_key);
308 /* Free private key */
310 SILC_PKCS_PRIVATE_KEY_FREE(silc_pkcs_pgp_private_key_free)
312 SilcPGPPrivateKey privkey = private_key;
313 silc_pgp_private_key_free(privkey);
318 SILC_PKCS_ENCRYPT(silc_pkcs_pgp_encrypt)
325 SILC_PKCS_DECRYPT(silc_pkcs_pgp_decrypt)
332 SILC_PKCS_SIGN(silc_pkcs_pgp_sign)
339 SILC_PKCS_VERIFY(silc_pkcs_pgp_verify)
344 /************************** OpenPGP RSA PKCS API ****************************/
346 /* Import OpenPGP compliant RSA public key */
348 SILC_PKCS_ALG_IMPORT_PUBLIC_KEY(silc_pgp_rsa_import_public_key)
350 SilcBufferStruct alg_key;
351 RsaPublicKey *pubkey;
352 unsigned char *n, *e;
353 SilcUInt16 n_len, e_len;
358 /* Allocate RSA public key */
359 *ret_public_key = pubkey = silc_calloc(1, sizeof(*pubkey));
363 /* Parse OpenPGP RSA public key */
364 silc_buffer_set(&alg_key, key, key_len);
365 if (silc_buffer_unformat(&alg_key,
367 SILC_STR_UINT16(&n_len),
371 n_len = (n_len + 7) / 8;
375 if (silc_buffer_unformat(&alg_key,
377 SILC_STR_DATA(&n, n_len),
378 SILC_STR_UINT16(&e_len),
382 e_len = (e_len + 7) / 8;
386 if (silc_buffer_unformat(&alg_key,
388 SILC_STR_DATA(&e, e_len),
392 /* Get MP integers */
393 silc_mp_init(&pubkey->n);
394 silc_mp_init(&pubkey->e);
395 silc_mp_bin2mp(n, n_len, &pubkey->n);
396 silc_mp_bin2mp(e, e_len, &pubkey->e);
399 pubkey->bits = silc_mp_sizeinbase(&pubkey->n, 2);
401 return silc_buffer_headlen(&alg_key);
408 /* Export OpenPGP compliant RSA public key */
410 SILC_PKCS_ALG_EXPORT_PUBLIC_KEY(silc_pgp_rsa_export_public_key)
412 RsaPublicKey *pubkey = public_key;
413 SilcBufferStruct alg_key;
414 unsigned char *n = NULL, *e = NULL, *ret;
415 SilcUInt16 n_len, e_len;
417 n_len = silc_mp_sizeinbase(&pubkey->n, 2);
418 e_len = silc_mp_sizeinbase(&pubkey->e, 2);
420 /* Encode MP integers */
421 n = silc_mp_mp2bin(&pubkey->n, 0, NULL);
424 e = silc_mp_mp2bin(&pubkey->e, 0, NULL);
428 memset(&alg_key, 0, sizeof(alg_key));
429 if (silc_buffer_format(&alg_key,
430 SILC_STR_UINT16(n_len),
431 SILC_STR_DATA(n, n_len),
432 SILC_STR_UINT16(e_len),
433 SILC_STR_DATA(e, e_len),
440 ret = silc_buffer_steal(&alg_key, ret_len);
449 /* Import OpenPGP compliant RSA private key */
451 SILC_PKCS_ALG_IMPORT_PRIVATE_KEY(silc_pgp_rsa_import_private_key)
453 SilcBufferStruct alg_key;
454 RsaPrivateKey *privkey;
455 unsigned char *d, *p, *q, *u;
456 SilcUInt16 d_len, p_len, q_len, u_len;
459 if (!ret_private_key)
462 /* Allocate RSA private key */
463 *ret_private_key = privkey = silc_calloc(1, sizeof(*privkey));
467 /* Parse OpenPGP RSA private key. In OpenPGP the u is p^-1 mod q, but
468 our RSA implementation expects q^-1 mod p (PKCS#1 compliant), thus
469 we reverse p and q to make it work. */
470 silc_buffer_set(&alg_key, key, key_len);
471 if (silc_buffer_unformat(&alg_key,
473 SILC_STR_UINT16(&d_len),
477 d_len = (d_len + 7) / 8;
481 if (silc_buffer_unformat(&alg_key,
483 SILC_STR_DATA(&d, d_len),
484 SILC_STR_UINT16(&q_len),
488 q_len = (q_len + 7) / 8;
492 if (silc_buffer_unformat(&alg_key,
494 SILC_STR_DATA(&q, q_len),
495 SILC_STR_UINT16(&p_len),
499 p_len = (p_len + 7) / 8;
503 if (silc_buffer_unformat(&alg_key,
505 SILC_STR_DATA(&p, p_len),
506 SILC_STR_UINT16(&u_len),
510 u_len = (u_len + 7) / 8;
514 if (silc_buffer_unformat(&alg_key,
516 SILC_STR_DATA(&u, u_len),
520 /* Get MP integers */
521 silc_mp_init(&privkey->d);
522 silc_mp_init(&privkey->p);
523 silc_mp_init(&privkey->q);
524 silc_mp_init(&privkey->qP);
525 silc_mp_bin2mp(d, d_len, &privkey->d);
526 silc_mp_bin2mp(p, p_len, &privkey->p);
527 silc_mp_bin2mp(q, q_len, &privkey->q);
528 silc_mp_bin2mp(u, u_len, &privkey->qP);
530 /* Fill in missing integers and pre-compute */
533 silc_mp_init(&privkey->n);
534 silc_mp_init(&privkey->e);
535 silc_mp_init(&privkey->dP);
536 silc_mp_init(&privkey->dQ);
537 silc_mp_mul(&privkey->n, &privkey->p, &privkey->q);
538 silc_mp_sub_ui(&pm1, &privkey->p, 1);
539 silc_mp_sub_ui(&qm1, &privkey->q, 1);
540 silc_mp_mod(&privkey->dP, &privkey->d, &pm1);
541 silc_mp_mod(&privkey->dQ, &privkey->d, &qm1);
542 silc_mp_uninit(&pm1);
543 silc_mp_uninit(&qm1);
546 privkey->bits = silc_mp_sizeinbase(&privkey->n, 2);
548 return silc_buffer_headlen(&alg_key);
555 /* Export OpenPGP compliant RSA private key */
557 SILC_PKCS_ALG_EXPORT_PRIVATE_KEY(silc_pgp_rsa_export_private_key)
559 RsaPrivateKey *privkey = private_key;
560 SilcBufferStruct alg_key;
561 unsigned char *d = NULL, *p = NULL, *q = NULL, *u = NULL, *ret;
562 SilcUInt16 d_len, p_len, q_len, u_len;
564 /* In OpenPGP the u is p^-1 mod q, but our RSA implementation uses
565 q^-1 mod p (PKCS#1 compliant), thus we reverse p and q to make the
567 d_len = silc_mp_sizeinbase(&privkey->d, 2);
568 p_len = silc_mp_sizeinbase(&privkey->q, 2);
569 q_len = silc_mp_sizeinbase(&privkey->p, 2);
570 u_len = silc_mp_sizeinbase(&privkey->qP, 2);
572 /* Encode MP integers */
573 d = silc_mp_mp2bin(&privkey->d, 0, NULL);
576 p = silc_mp_mp2bin(&privkey->q, 0, NULL);
579 q = silc_mp_mp2bin(&privkey->p, 0, NULL);
582 u = silc_mp_mp2bin(&privkey->qP, 0, NULL);
586 memset(&alg_key, 0, sizeof(alg_key));
587 if (silc_buffer_format(&alg_key,
588 SILC_STR_UINT16(d_len),
589 SILC_STR_DATA(d, d_len),
590 SILC_STR_UINT16(p_len),
591 SILC_STR_DATA(p, p_len),
592 SILC_STR_UINT16(q_len),
593 SILC_STR_DATA(q, q_len),
594 SILC_STR_UINT16(u_len),
595 SILC_STR_DATA(u, u_len),
604 ret = silc_buffer_steal(&alg_key, ret_len);
615 /************************** OpenPGP DSA PKCS API ****************************/
617 /* Import OpenPGP compliant DSA public key */
619 SILC_PKCS_ALG_IMPORT_PUBLIC_KEY(silc_pgp_dsa_import_public_key)
621 SilcBufferStruct alg_key;
622 DsaPublicKey *pubkey;
623 unsigned char *p, *q, *g, *y;
624 SilcUInt16 p_len, q_len, g_len, y_len;
629 /* Allocate DSA public key */
630 *ret_public_key = pubkey = silc_calloc(1, sizeof(*pubkey));
634 /* Parse OpenPGP DSA public key */
635 silc_buffer_set(&alg_key, key, key_len);
636 if (silc_buffer_unformat(&alg_key,
638 SILC_STR_UINT16(&p_len),
642 p_len = (p_len + 7) / 8;
646 if (silc_buffer_unformat(&alg_key,
648 SILC_STR_DATA(&p, p_len),
649 SILC_STR_UINT16(&q_len),
653 q_len = (q_len + 7) / 8;
657 if (silc_buffer_unformat(&alg_key,
659 SILC_STR_DATA(&q, q_len),
660 SILC_STR_UINT16(&g_len),
664 g_len = (g_len + 7) / 8;
668 if (silc_buffer_unformat(&alg_key,
670 SILC_STR_DATA(&g, g_len),
671 SILC_STR_UINT16(&y_len),
675 y_len = (y_len + 7) / 8;
679 if (silc_buffer_unformat(&alg_key,
681 SILC_STR_DATA(&y, y_len),
685 /* Get MP integers */
686 silc_mp_init(&pubkey->p);
687 silc_mp_init(&pubkey->q);
688 silc_mp_init(&pubkey->g);
689 silc_mp_init(&pubkey->y);
690 silc_mp_bin2mp(p, p_len, &pubkey->p);
691 silc_mp_bin2mp(q, q_len, &pubkey->q);
692 silc_mp_bin2mp(g, g_len, &pubkey->g);
693 silc_mp_bin2mp(y, y_len, &pubkey->y);
696 pubkey->bits = silc_mp_sizeinbase(&pubkey->p, 2);
698 return silc_buffer_headlen(&alg_key);
705 /* Export OpenPGP compliant DSA public key */
707 SILC_PKCS_ALG_EXPORT_PUBLIC_KEY(silc_pgp_dsa_export_public_key)
712 /* Import OpenPGP compliant DSA private key */
714 SILC_PKCS_ALG_IMPORT_PRIVATE_KEY(silc_pgp_dsa_import_private_key)
716 SilcBufferStruct alg_key;
717 DsaPrivateKey *privkey;
721 if (!ret_private_key)
724 /* Allocate DSA private key */
725 *ret_private_key = privkey = silc_calloc(1, sizeof(*privkey));
729 /* Parse OpenPGP DSA private key. */
730 silc_buffer_set(&alg_key, key, key_len);
731 if (silc_buffer_unformat(&alg_key,
733 SILC_STR_UINT16(&x_len),
737 x_len = (x_len + 7) / 8;
741 if (silc_buffer_unformat(&alg_key,
743 SILC_STR_DATA(&x, x_len),
747 /* Get MP integers */
748 silc_mp_init(&privkey->x);
749 silc_mp_bin2mp(x, x_len, &privkey->x);
751 return silc_buffer_headlen(&alg_key);
758 /* Export OpenPGP compliant DSA private key */
760 SILC_PKCS_ALG_EXPORT_PRIVATE_KEY(silc_pgp_dsa_export_private_key)