5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2007 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.
23 /****************************** Key generation *******************************/
25 /* Generate new SILC key pair. */
27 SilcBool silc_pkcs_silc_generate_key(const char *algorithm,
28 SilcUInt32 bits_key_len,
29 const char *identifier,
31 SilcPublicKey *ret_public_key,
32 SilcPrivateKey *ret_private_key)
34 SilcSILCPublicKey pubkey;
35 SilcSILCPrivateKey privkey;
36 const SilcPKCSAlgorithm *alg;
37 const SilcPKCSObject *pkcs;
40 SILC_LOG_DEBUG(("Generating SILC %s key pair with key length %d bits",
41 algorithm, bits_key_len));
46 pkcs = silc_pkcs_find_pkcs(SILC_PKCS_SILC);
50 /* Allocate SILC public key */
51 pubkey = silc_calloc(1, sizeof(*pubkey));
55 /* Decode identifier */
56 if (!silc_pkcs_silc_decode_identifier(identifier, &pubkey->identifier))
59 if (pubkey->identifier.version && atoi(pubkey->identifier.version) >= 2)
64 /* Allocate algorithm */
65 alg = silc_pkcs_find_algorithm(algorithm, (version == 1 ? "pkcs1-no-oid" :
73 /* Allocate SILC private key */
74 privkey = silc_calloc(1, sizeof(*privkey));
81 /* Allocate public key */
82 *ret_public_key = silc_calloc(1, sizeof(**ret_public_key));
83 if (!(*ret_public_key)) {
88 (*ret_public_key)->pkcs = pkcs;
89 (*ret_public_key)->public_key = pubkey;
91 /* Allocate private key */
92 *ret_private_key = silc_calloc(1, sizeof(**ret_private_key));
93 if (!(*ret_private_key)) {
96 silc_free(*ret_public_key);
99 (*ret_private_key)->pkcs = pkcs;
100 (*ret_private_key)->private_key = privkey;
102 /* Generate the algorithm key pair */
103 if (!alg->generate_key(alg, bits_key_len, rng, &pubkey->public_key,
104 &privkey->private_key)) {
107 silc_free(*ret_public_key);
108 silc_free(*ret_private_key);
116 /**************************** Utility functions ******************************/
118 /* Decodes the provided `identifier' */
120 SilcBool silc_pkcs_silc_decode_identifier(const char *identifier,
121 SilcPublicKeyIdentifier ident)
126 /* Protocol says that at least UN and HN must be provided as identifier */
127 if (!strstr(identifier, "UN=") && !strstr(identifier, "HN=")) {
128 SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
133 cp = (char *)identifier;
135 len = strcspn(cp, ",");
140 if (len - 1 >= 0 && cp[len - 1] == '\\') {
142 if (len + 1 > strlen(cp)) {
147 len = strcspn(cp, ",") + len;
152 if (len - 1 >= 0 && cp[len - 1] != '\\')
160 item = silc_calloc(len + 1, sizeof(char));
163 if (len > strlen(cp))
165 memcpy(item, cp, len);
167 if (strstr(item, "UN="))
168 ident->username = strdup(item + strcspn(cp, "=") + 1);
169 else if (strstr(item, "HN="))
170 ident->host = strdup(item + strcspn(cp, "=") + 1);
171 else if (strstr(item, "RN="))
172 ident->realname = strdup(item + strcspn(cp, "=") + 1);
173 else if (strstr(item, "E="))
174 ident->email = strdup(item + strcspn(cp, "=") + 1);
175 else if (strstr(item, "O="))
176 ident->org = strdup(item + strcspn(cp, "=") + 1);
177 else if (strstr(item, "C="))
178 ident->country = strdup(item + strcspn(cp, "=") + 1);
179 else if (strstr(item, "V="))
180 ident->version = strdup(item + strcspn(cp, "=") + 1);
195 /* Encodes and returns SILC public key identifier. If some of the
196 arguments is NULL those are not encoded into the identifier string.
197 Protocol says that at least username and host must be provided. */
199 char *silc_pkcs_silc_encode_identifier(SilcStack stack,
200 char *username, char *host,
201 char *realname, char *email,
202 char *org, char *country,
205 SilcBufferStruct buf;
208 if (!username || !host)
210 if (strlen(username) < 3 || strlen(host) < 3)
213 memset(&buf, 0, sizeof(buf));
216 silc_buffer_sformat(stack, &buf,
218 SILC_STR_UI32_STRING("UN="),
219 SILC_STR_UI32_STRING(username),
223 silc_buffer_sformat(stack, &buf,
225 SILC_STR_UI32_STRING(", "),
226 SILC_STR_UI32_STRING("HN="),
227 SILC_STR_UI32_STRING(host),
231 silc_buffer_sformat(stack, &buf,
233 SILC_STR_UI32_STRING(", "),
234 SILC_STR_UI32_STRING("RN="),
235 SILC_STR_UI32_STRING(realname),
239 silc_buffer_sformat(stack, &buf,
241 SILC_STR_UI32_STRING(", "),
242 SILC_STR_UI32_STRING("E="),
243 SILC_STR_UI32_STRING(email),
247 silc_buffer_sformat(stack, &buf,
249 SILC_STR_UI32_STRING(", "),
250 SILC_STR_UI32_STRING("O="),
251 SILC_STR_UI32_STRING(org),
255 silc_buffer_sformat(stack, &buf,
257 SILC_STR_UI32_STRING(", "),
258 SILC_STR_UI32_STRING("C="),
259 SILC_STR_UI32_STRING(country),
263 if (strlen(version) > 1 || !isdigit(version[0])) {
264 silc_buffer_spurge(stack, &buf);
267 silc_buffer_sformat(stack, &buf,
269 SILC_STR_UI32_STRING(", "),
270 SILC_STR_UI32_STRING("V="),
271 SILC_STR_UI32_STRING(version),
275 silc_buffer_sformat(stack, &buf, SILC_STR_UI_CHAR(0), SILC_STR_END);
277 identifier = silc_buffer_steal(&buf, NULL);
281 /* Return SILC public key version */
283 int silc_pkcs_silc_public_key_version(SilcPublicKey public_key)
285 SilcSILCPublicKey silc_pubkey;
287 if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC)
290 silc_pubkey = public_key->public_key;
292 /* If version identifire is not present it is version 1. */
293 if (!silc_pubkey->identifier.version)
296 return atoi(silc_pubkey->identifier.version);
299 /*************************** Public key routines *****************************/
301 /* Returns PKCS algorithm context */
303 const SilcPKCSAlgorithm *
304 silc_pkcs_silc_get_algorithm(const struct SilcPKCSObjectStruct *pkcs,
307 SilcSILCPublicKey silc_pubkey = public_key;
308 return silc_pubkey->pkcs;
311 /* Imports SILC protocol style public key from SILC public key file */
314 silc_pkcs_silc_import_public_key_file(const struct SilcPKCSObjectStruct *pkcs,
315 unsigned char *filedata,
316 SilcUInt32 filedata_len,
317 SilcPKCSFileEncoding encoding,
318 void **ret_public_key)
321 unsigned char *data = NULL;
324 SILC_LOG_DEBUG(("Parsing SILC public key file"));
329 /* Check start of file and remove header from the data. */
330 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
331 if (filedata_len < len + strlen(SILC_PKCS_PUBLIC_KEYFILE_END)) {
332 SILC_LOG_ERROR(("Malformed SILC public key header"));
335 for (i = 0; i < len; i++) {
336 if (*filedata != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
337 SILC_LOG_ERROR(("Malformed SILC public key header"));
342 filedata_len -= (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
343 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
346 case SILC_PKCS_FILE_BIN:
349 case SILC_PKCS_FILE_BASE64:
350 data = silc_base64_decode(NULL, filedata, filedata_len, &filedata_len);
357 ret = silc_pkcs_silc_import_public_key(pkcs, filedata, filedata_len,
361 return ret ? TRUE : FALSE;
364 /* Imports SILC protocol style public key */
366 int silc_pkcs_silc_import_public_key(const struct SilcPKCSObjectStruct *pkcs,
369 void **ret_public_key)
371 const SilcPKCSAlgorithm *alg;
372 SilcBufferStruct buf, alg_key;
373 SilcSILCPublicKey silc_pubkey = NULL;
374 SilcAsn1 asn1 = NULL;
375 SilcUInt32 totlen, keydata_len;
376 SilcUInt16 pkcs_len, identifier_len;
377 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
380 SILC_LOG_DEBUG(("Parsing SILC public key"));
385 silc_buffer_set(&buf, key, key_len);
388 ret = silc_buffer_unformat(&buf,
390 SILC_STR_UI_INT(&totlen),
395 /* Backwards compatibility */
396 if (totlen == key_len)
399 if (totlen + 4 != key_len)
402 /* Get algorithm name and identifier */
404 silc_buffer_unformat(&buf,
406 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
407 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
412 if (pkcs_len < 1 || identifier_len < 3 ||
413 pkcs_len + identifier_len > totlen)
417 keydata_len = silc_buffer_len(&buf);
418 ret = silc_buffer_unformat(&buf,
419 SILC_STR_DATA(&key_data, keydata_len),
424 /* Allocate SILC public key context */
425 silc_pubkey = silc_calloc(1, sizeof(*silc_pubkey));
429 /* Decode SILC identifier */
430 if (!silc_pkcs_silc_decode_identifier(ident, &silc_pubkey->identifier))
433 asn1 = silc_asn1_alloc(NULL);
437 SILC_LOG_DEBUG(("Public key version %s",
438 (!silc_pubkey->identifier.version ? "1" :
439 silc_pubkey->identifier.version)));
441 if (!strcmp(pkcs_name, "rsa")) {
442 /* Parse the SILC RSA public key */
443 SilcUInt32 e_len, n_len;
446 /* Get PKCS object. Different PKCS #1 scheme is used with different
448 if (!silc_pubkey->identifier.version ||
449 atoi(silc_pubkey->identifier.version) <= 1) {
451 alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid");
453 /* Version 2 and newer */
454 alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1");
457 SILC_LOG_DEBUG(("Unsupported PKCS algorithm: rsa"));
460 silc_pubkey->pkcs = alg;
464 SILC_GET32_MSB(e_len, key_data);
465 if (!e_len || e_len + 4 > keydata_len)
468 silc_mp_bin2mp(key_data + 4, e_len, &e);
469 if (keydata_len < 4 + e_len + 4) {
473 SILC_GET32_MSB(n_len, key_data + 4 + e_len);
474 if (!n_len || e_len + 4 + n_len + 4 > keydata_len) {
479 silc_mp_bin2mp(key_data + 4 + e_len + 4, n_len, &n);
481 /* Encode to PKCS #1 format */
482 memset(&alg_key, 0, sizeof(alg_key));
483 if (!silc_asn1_encode(asn1, &alg_key,
487 SILC_ASN1_END, SILC_ASN1_END)) {
496 } else if (!strcmp(pkcs_name, "dsa")) {
497 SILC_NOT_IMPLEMENTED("DSA SILC Public Key");
501 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
505 /* Import PKCS algorithm public key */
506 if (!alg->import_public_key(alg, alg_key.data, silc_buffer_len(&alg_key),
507 &silc_pubkey->public_key))
510 silc_free(pkcs_name);
512 silc_asn1_free(asn1);
514 *ret_public_key = silc_pubkey;
519 silc_free(pkcs_name);
521 silc_free(silc_pubkey);
523 silc_asn1_free(asn1);
527 /* Exports public key as SILC protocol style public key file */
530 silc_pkcs_silc_export_public_key_file(const struct SilcPKCSObjectStruct *pkcs,
533 SilcPKCSFileEncoding encoding,
537 unsigned char *key, *data;
540 SILC_LOG_DEBUG(("Encoding SILC public key file"));
543 key = silc_pkcs_silc_export_public_key(pkcs, stack, public_key, &key_len);
548 case SILC_PKCS_FILE_BIN:
551 case SILC_PKCS_FILE_BASE64:
552 data = silc_base64_encode_file(stack, key, key_len);
555 silc_sfree(stack, key);
557 key_len = strlen(data);
561 /* Encode SILC public key file */
562 buf = silc_buffer_salloc_size(stack, key_len +
563 (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
564 strlen(SILC_PKCS_PUBLIC_KEYFILE_END)));
566 silc_sfree(stack, key);
570 if (silc_buffer_sformat(stack, buf,
571 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
572 SILC_STR_UI_XNSTRING(key, key_len),
573 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
575 silc_buffer_sfree(stack, buf);
576 silc_sfree(stack, key);
580 silc_sfree(stack, key);
581 key = silc_buffer_steal(buf, ret_len);
582 silc_buffer_sfree(stack, buf);
587 /* Exports public key as SILC protocol style public key */
590 silc_pkcs_silc_export_public_key(const struct SilcPKCSObjectStruct *pkcs,
595 SilcSILCPublicKey silc_pubkey = public_key;
596 const SilcPKCSAlgorithm *alg = silc_pubkey->pkcs;
597 SilcBufferStruct alg_key;
598 SilcBuffer buf = NULL;
599 SilcAsn1 asn1 = NULL;
600 unsigned char *pk = NULL, *key = NULL, *ret;
601 SilcUInt32 pk_len, key_len, totlen;
604 SILC_LOG_DEBUG(("Encoding SILC public key"));
606 /* Export PKCS algorithm public key */
607 if (alg->export_public_key)
608 pk = alg->export_public_key(alg, stack, silc_pubkey->public_key, &pk_len);
610 SILC_LOG_ERROR(("Error exporting PKCS algorithm key"));
613 silc_buffer_set(&alg_key, pk, pk_len);
615 /* Encode identifier */
617 silc_pkcs_silc_encode_identifier(stack,
618 silc_pubkey->identifier.username,
619 silc_pubkey->identifier.host,
620 silc_pubkey->identifier.realname,
621 silc_pubkey->identifier.email,
622 silc_pubkey->identifier.org,
623 silc_pubkey->identifier.country,
624 silc_pubkey->identifier.version);
626 SILC_LOG_ERROR(("Error encoding SILC public key identifier"));
630 asn1 = silc_asn1_alloc(stack);
634 if (!strcmp(alg->name, "rsa")) {
635 /* Parse the PKCS #1 public key */
637 SilcUInt32 n_len, e_len;
638 unsigned char *nb, *eb;
640 memset(&n, 0, sizeof(n));
641 memset(&e, 0, sizeof(e));
642 if (!silc_asn1_decode(asn1, &alg_key,
646 SILC_ASN1_END, SILC_ASN1_END))
649 /* Encode to SILC RSA public key */
650 eb = silc_mp_mp2bin(&e, 0, &e_len);
653 nb = silc_mp_mp2bin(&n, 0, &n_len);
656 key_len = e_len + 4 + n_len + 4;
657 key = silc_scalloc(stack, key_len, sizeof(*key));
661 /* Put e length and e */
662 SILC_PUT32_MSB(e_len, key);
663 memcpy(key + 4, eb, e_len);
665 /* Put n length and n. */
666 SILC_PUT32_MSB(n_len, key + 4 + e_len);
667 memcpy(key + 4 + e_len + 4, nb, n_len);
672 } else if (!strcmp(alg->name, "dsa")) {
673 SILC_NOT_IMPLEMENTED("SILC DSA Public Key");
677 SILC_LOG_ERROR(("Unsupported PKCS algorithm: %s", alg->name));
681 /* Encode SILC Public Key */
682 totlen = 2 + strlen(alg->name) + 2 + strlen(identifier) + key_len;
683 buf = silc_buffer_salloc_size(stack, totlen + 4);
686 if (silc_buffer_sformat(stack, buf,
687 SILC_STR_UI_INT(totlen),
688 SILC_STR_UI_SHORT(strlen(alg->name)),
689 SILC_STR_UI32_STRING(alg->name),
690 SILC_STR_UI_SHORT(strlen(identifier)),
691 SILC_STR_UI32_STRING(identifier),
692 SILC_STR_UI_XNSTRING(key, key_len),
696 ret = silc_buffer_steal(buf, ret_len);
697 silc_buffer_sfree(stack, buf);
698 silc_sfree(stack, key);
699 silc_sfree(stack, identifier);
700 silc_buffer_spurge(stack, &alg_key);
701 silc_asn1_free(asn1);
706 silc_sfree(stack, identifier);
707 silc_sfree(stack, pk);
708 silc_sfree(stack, key);
709 silc_buffer_sfree(stack, buf);
711 silc_asn1_free(asn1);
715 /* Return key length */
718 silc_pkcs_silc_public_key_bitlen(const struct SilcPKCSObjectStruct *pkcs,
721 SilcSILCPublicKey silc_pubkey = public_key;
722 return silc_pubkey->pkcs->public_key_bitlen(silc_pubkey->pkcs,
723 silc_pubkey->public_key);
726 /* Copy public key */
728 void *silc_pkcs_silc_public_key_copy(const struct SilcPKCSObjectStruct *pkcs,
731 SilcSILCPublicKey silc_pubkey = public_key, new_pubkey;
732 SilcPublicKeyIdentifier ident = &silc_pubkey->identifier;
734 new_pubkey = silc_calloc(1, sizeof(*new_pubkey));
737 new_pubkey->pkcs = silc_pubkey->pkcs;
739 new_pubkey->public_key =
740 silc_pubkey->pkcs->public_key_copy(silc_pubkey->pkcs,
741 silc_pubkey->public_key);
742 if (!new_pubkey->public_key) {
743 silc_free(new_pubkey);
748 new_pubkey->identifier.username =
749 silc_memdup(ident->username, strlen(ident->username));
751 new_pubkey->identifier.host =
752 silc_memdup(ident->host, strlen(ident->host));
754 new_pubkey->identifier.realname =
755 silc_memdup(ident->realname, strlen(ident->realname));
757 new_pubkey->identifier.email =
758 silc_memdup(ident->email, strlen(ident->email));
760 new_pubkey->identifier.org =
761 silc_memdup(ident->org, strlen(ident->org));
763 new_pubkey->identifier.country =
764 silc_memdup(ident->country, strlen(ident->country));
766 new_pubkey->identifier.version =
767 silc_memdup(ident->version, strlen(ident->version));
772 /* Compares public keys */
775 silc_pkcs_silc_public_key_compare(const struct SilcPKCSObjectStruct *pkcs,
776 void *key1, void *key2)
778 SilcSILCPublicKey k1 = key1, k2 = key2;
780 if (strcmp(k1->pkcs->name, k2->pkcs->name))
783 if ((k1->identifier.username && !k2->identifier.username) ||
784 (!k1->identifier.username && k2->identifier.username) ||
785 (k1->identifier.username && k2->identifier.username &&
786 strcmp(k1->identifier.username, k2->identifier.username)))
789 if ((k1->identifier.host && !k2->identifier.host) ||
790 (!k1->identifier.host && k2->identifier.host) ||
791 (k1->identifier.host && k2->identifier.host &&
792 strcmp(k1->identifier.host, k2->identifier.host)))
795 if ((k1->identifier.realname && !k2->identifier.realname) ||
796 (!k1->identifier.realname && k2->identifier.realname) ||
797 (k1->identifier.realname && k2->identifier.realname &&
798 strcmp(k1->identifier.realname, k2->identifier.realname)))
801 if ((k1->identifier.email && !k2->identifier.email) ||
802 (!k1->identifier.email && k2->identifier.email) ||
803 (k1->identifier.email && k2->identifier.email &&
804 strcmp(k1->identifier.email, k2->identifier.email)))
807 if ((k1->identifier.org && !k2->identifier.org) ||
808 (!k1->identifier.org && k2->identifier.org) ||
809 (k1->identifier.org && k2->identifier.org &&
810 strcmp(k1->identifier.org, k2->identifier.org)))
813 if ((k1->identifier.country && !k2->identifier.country) ||
814 (!k1->identifier.country && k2->identifier.country) ||
815 (k1->identifier.country && k2->identifier.country &&
816 strcmp(k1->identifier.country, k2->identifier.country)))
819 if ((k1->identifier.version && !k2->identifier.version) ||
820 (!k1->identifier.version && k2->identifier.version) ||
821 (k1->identifier.version && k2->identifier.version &&
822 strcmp(k1->identifier.version, k2->identifier.version)))
825 return k1->pkcs->public_key_compare(k1->pkcs, k1->public_key, k2->public_key);
828 /* Frees public key */
830 void silc_pkcs_silc_public_key_free(const struct SilcPKCSObjectStruct *pkcs,
833 SilcSILCPublicKey silc_pubkey = public_key;
835 silc_pubkey->pkcs->public_key_free(silc_pubkey->pkcs,
836 silc_pubkey->public_key);
838 silc_free(silc_pubkey->identifier.username);
839 silc_free(silc_pubkey->identifier.host);
840 silc_free(silc_pubkey->identifier.realname);
841 silc_free(silc_pubkey->identifier.email);
842 silc_free(silc_pubkey->identifier.org);
843 silc_free(silc_pubkey->identifier.country);
844 silc_free(silc_pubkey->identifier.version);
845 silc_free(silc_pubkey);
849 /*************************** Private key routines ****************************/
851 /* Private key file magic */
852 #define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
854 /* Imports SILC implementation style private key file */
857 silc_pkcs_silc_import_private_key_file(const struct SilcPKCSObjectStruct *pkcs,
858 unsigned char *filedata,
859 SilcUInt32 filedata_len,
860 const char *passphrase,
861 SilcUInt32 passphrase_len,
862 SilcPKCSFileEncoding encoding,
863 void **ret_private_key)
869 unsigned char tmp[32], keymat[64], *data = NULL;
870 SilcUInt32 i, len, magic, mac_len;
873 SILC_LOG_DEBUG(("Parsing SILC private key file"));
875 /* Check start of file and remove header from the data. */
876 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
877 if (filedata_len < len + strlen(SILC_PKCS_PRIVATE_KEYFILE_END)) {
878 SILC_LOG_ERROR(("Malformed SILC private key header"));
881 for (i = 0; i < len; i++) {
882 if (*filedata != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
883 SILC_LOG_ERROR(("Malformed SILC private key header"));
889 len = filedata_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
890 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
893 case SILC_PKCS_FILE_BIN:
896 case SILC_PKCS_FILE_BASE64:
897 data = silc_base64_decode(NULL, filedata, filedata_len, &len);
904 memset(tmp, 0, sizeof(tmp));
905 memset(keymat, 0, sizeof(keymat));
907 /* Check file magic */
908 SILC_GET32_MSB(magic, filedata);
909 if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
910 SILC_LOG_DEBUG(("Private key does not have correct magic"));
914 /* Allocate the AES cipher */
915 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
916 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
919 blocklen = silc_cipher_get_block_len(aes);
920 if (blocklen * 2 > sizeof(tmp)) {
921 silc_cipher_free(aes);
925 /* Allocate SHA1 hash */
926 if (!silc_hash_alloc("sha1", &sha1)) {
927 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
928 silc_cipher_free(aes);
933 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
934 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
935 silc_hash_free(sha1);
936 silc_cipher_free(aes);
940 /* Derive the decryption key from the provided key material. The key
941 is 256 bits length, and derived by taking hash of the data, then
942 re-hashing the data and the previous digest, and using the first and
943 second digest as the key. */
944 silc_hash_init(sha1);
945 silc_hash_update(sha1, passphrase, passphrase_len);
946 silc_hash_final(sha1, keymat);
947 silc_hash_init(sha1);
948 silc_hash_update(sha1, passphrase, passphrase_len);
949 silc_hash_update(sha1, keymat, 16);
950 silc_hash_final(sha1, keymat + 16);
952 /* Set the key to the cipher */
953 silc_cipher_set_key(aes, keymat, 256, FALSE);
955 /* First, verify the MAC of the private key data */
956 mac_len = silc_hmac_len(sha1hmac);
957 silc_hmac_init_with_key(sha1hmac, keymat, 16);
958 silc_hmac_update(sha1hmac, filedata, len - mac_len);
959 silc_hmac_final(sha1hmac, tmp, NULL);
960 if (memcmp(tmp, filedata + (len - mac_len), mac_len)) {
961 SILC_LOG_DEBUG(("Integrity check for private key failed"));
962 memset(keymat, 0, sizeof(keymat));
963 memset(tmp, 0, sizeof(tmp));
964 silc_hmac_free(sha1hmac);
965 silc_hash_free(sha1);
966 silc_cipher_free(aes);
972 /* Decrypt the private key buffer */
973 silc_cipher_decrypt(aes, filedata, filedata, len - mac_len, NULL);
974 SILC_GET32_MSB(i, filedata);
976 SILC_LOG_DEBUG(("Bad private key length in buffer!"));
977 memset(keymat, 0, sizeof(keymat));
978 memset(tmp, 0, sizeof(tmp));
979 silc_hmac_free(sha1hmac);
980 silc_hash_free(sha1);
981 silc_cipher_free(aes);
988 memset(keymat, 0, sizeof(keymat));
989 memset(tmp, 0, sizeof(tmp));
990 silc_hmac_free(sha1hmac);
991 silc_hash_free(sha1);
992 silc_cipher_free(aes);
994 /* Import the private key */
995 ret = silc_pkcs_silc_import_private_key(pkcs, filedata, len, ret_private_key);
999 return ret ? TRUE : FALSE;
1002 /* Private key version */
1003 #define SILC_PRIVATE_KEY_VERSION_1 0x82171273
1004 #define SILC_PRIVATE_KEY_VERSION_2 0xf911a3d1
1006 /* Imports SILC implementation style private key */
1008 int silc_pkcs_silc_import_private_key(const struct SilcPKCSObjectStruct *pkcs,
1011 void **ret_private_key)
1013 SilcBufferStruct buf;
1014 const SilcPKCSAlgorithm *alg;
1015 SilcBufferStruct alg_key;
1016 SilcSILCPrivateKey silc_privkey = NULL;
1017 SilcAsn1 asn1 = NULL;
1018 SilcUInt16 pkcs_len;
1019 SilcUInt32 keydata_len;
1020 unsigned char *pkcs_name = NULL, *key_data;
1023 SILC_LOG_DEBUG(("Parsing SILC private key"));
1025 if (!ret_private_key)
1028 silc_buffer_set(&buf, (unsigned char *)key, key_len);
1030 /* Get algorithm name and identifier */
1032 silc_buffer_unformat(&buf,
1033 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
1036 SILC_LOG_DEBUG(("Cannot decode private key buffer"));
1040 if (pkcs_len < 1 || pkcs_len > silc_buffer_truelen(&buf)) {
1041 SILC_LOG_DEBUG(("Malformed private key buffer"));
1045 /* Get key data. We assume that rest of the buffer is key data. */
1046 silc_buffer_pull(&buf, 2 + pkcs_len);
1047 keydata_len = silc_buffer_len(&buf);
1048 ret = silc_buffer_unformat(&buf,
1049 SILC_STR_UI_XNSTRING(&key_data, keydata_len),
1054 /* Allocate SILC private key context */
1055 silc_privkey = silc_calloc(1, sizeof(*silc_privkey));
1059 asn1 = silc_asn1_alloc(NULL);
1063 if (!strcmp(pkcs_name, "rsa")) {
1064 /* Parse the RSA SILC private key */
1066 SilcMPInt n, e, d, dp, dq, qp, p, q;
1068 SilcUInt32 len, ver;
1070 if (keydata_len < 4)
1072 silc_buffer_set(&k, key_data, keydata_len);
1074 /* Get version. Key without the version is old style private key
1075 and we need to do some computation to get it to correct format. */
1076 if (silc_buffer_unformat(&k,
1077 SILC_STR_UI_INT(&ver),
1080 silc_buffer_pull(&k, 4);
1082 if (ver != SILC_PRIVATE_KEY_VERSION_1 &&
1083 ver != SILC_PRIVATE_KEY_VERSION_2) {
1087 if (silc_buffer_unformat(&k,
1088 SILC_STR_UI_INT(&len),
1091 silc_buffer_pull(&k, 4);
1094 /* Get PKCS object. Different PKCS #1 scheme is used with different
1096 if (ver == 0 || ver == SILC_PRIVATE_KEY_VERSION_1) {
1097 /* Version 0 and 1 */
1098 alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid");
1100 /* Version 2 and newer */
1101 alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1");
1104 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1107 silc_privkey->pkcs = alg;
1109 SILC_LOG_DEBUG(("Private key version %s",
1110 (ver == SILC_PRIVATE_KEY_VERSION_1 ? "1" :
1111 ver == SILC_PRIVATE_KEY_VERSION_2 ? "2" : "0")));
1114 if (silc_buffer_unformat(&k,
1115 SILC_STR_DATA(&tmp, len),
1119 silc_mp_bin2mp(tmp, len, &e);
1120 silc_buffer_pull(&k, len);
1123 if (silc_buffer_unformat(&k,
1124 SILC_STR_UI_INT(&len),
1127 silc_buffer_pull(&k, 4);
1128 if (silc_buffer_unformat(&k,
1129 SILC_STR_DATA(&tmp, len),
1133 silc_mp_bin2mp(tmp, len, &n);
1134 silc_buffer_pull(&k, len);
1137 if (silc_buffer_unformat(&k,
1138 SILC_STR_UI_INT(&len),
1141 silc_buffer_pull(&k, 4);
1142 if (silc_buffer_unformat(&k,
1143 SILC_STR_DATA(&tmp, len),
1147 silc_mp_bin2mp(tmp, len, &d);
1148 silc_buffer_pull(&k, len);
1151 if (silc_buffer_unformat(&k,
1152 SILC_STR_UI_INT(&len),
1155 silc_buffer_pull(&k, 4);
1156 if (silc_buffer_unformat(&k,
1157 SILC_STR_DATA(&tmp, len),
1161 silc_mp_bin2mp(tmp, len, &dp);
1162 silc_buffer_pull(&k, len);
1165 if (silc_buffer_unformat(&k,
1166 SILC_STR_UI_INT(&len),
1169 silc_buffer_pull(&k, 4);
1170 if (silc_buffer_unformat(&k,
1171 SILC_STR_DATA(&tmp, len),
1175 silc_mp_bin2mp(tmp, len, &dq);
1176 silc_buffer_pull(&k, len);
1182 if (silc_buffer_unformat(&k,
1183 SILC_STR_UI_INT(&len),
1186 silc_buffer_pull(&k, 4);
1187 if (silc_buffer_len(&k) < len)
1189 silc_buffer_pull(&k, len);
1192 if (silc_buffer_unformat(&k,
1193 SILC_STR_UI_INT(&len),
1196 silc_buffer_pull(&k, 4);
1197 if (silc_buffer_len(&k) < len)
1199 silc_buffer_pull(&k, len);
1204 if (silc_buffer_unformat(&k,
1205 SILC_STR_UI_INT(&len),
1208 silc_buffer_pull(&k, 4);
1209 if (silc_buffer_unformat(&k,
1210 SILC_STR_DATA(&tmp, len),
1214 silc_mp_bin2mp(tmp, len, &qp);
1215 silc_buffer_pull(&k, len);
1219 if (silc_buffer_unformat(&k,
1220 SILC_STR_UI_INT(&len),
1223 silc_buffer_pull(&k, 4);
1224 if (silc_buffer_unformat(&k,
1225 SILC_STR_DATA(&tmp, len),
1229 silc_mp_bin2mp(tmp, len, &p);
1230 silc_buffer_pull(&k, len);
1233 if (silc_buffer_unformat(&k,
1234 SILC_STR_UI_INT(&len),
1237 silc_buffer_pull(&k, 4);
1238 if (silc_buffer_unformat(&k,
1239 SILC_STR_DATA(&tmp, len),
1243 silc_mp_bin2mp(tmp, len, &q);
1244 silc_buffer_pull(&k, len);
1247 /* Old version. Compute to new version */
1248 SILC_LOG_DEBUG(("Old version private key"));
1250 silc_mp_modinv(&qp, &q, &p);
1253 /* Encode to PKCS #1 format */
1254 memset(&alg_key, 0, sizeof(alg_key));
1255 if (!silc_asn1_encode(asn1, &alg_key,
1257 SILC_ASN1_SHORT_INT(0),
1266 SILC_ASN1_END, SILC_ASN1_END))
1275 silc_mp_uninit(&dp);
1276 silc_mp_uninit(&dq);
1277 silc_mp_uninit(&qp);
1279 } else if (!strcmp(pkcs_name, "dsa")) {
1280 SILC_NOT_IMPLEMENTED("DSA SILC Private Key");
1284 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1288 /* Import PKCS algorithm private key */
1289 if (!alg->import_private_key(alg, alg_key.data, silc_buffer_len(&alg_key),
1290 &silc_privkey->private_key))
1293 silc_free(pkcs_name);
1294 silc_asn1_free(asn1);
1296 *ret_private_key = silc_privkey;
1301 silc_free(pkcs_name);
1302 silc_free(silc_privkey);
1304 silc_asn1_free(asn1);
1305 SILC_LOG_ERROR(("Malformed SILC private key "));
1309 /* Exports private key as SILC implementation style private key file */
1312 silc_pkcs_silc_export_private_key_file(const struct SilcPKCSObjectStruct *pkcs,
1315 const char *passphrase,
1316 SilcUInt32 passphrase_len,
1317 SilcPKCSFileEncoding encoding,
1319 SilcUInt32 *ret_len)
1324 SilcBuffer buf, enc;
1325 SilcUInt32 len, blocklen, padlen, key_len;
1326 unsigned char *key, *data;
1327 unsigned char tmp[32], keymat[64];
1330 SILC_LOG_DEBUG(("Encoding SILC private key file"));
1332 /* Export the private key */
1333 key = silc_pkcs_silc_export_private_key(pkcs, stack, private_key, &key_len);
1337 memset(tmp, 0, sizeof(tmp));
1338 memset(keymat, 0, sizeof(keymat));
1340 /* Allocate the AES cipher */
1341 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1342 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1343 silc_sfree(stack, key);
1346 blocklen = silc_cipher_get_block_len(aes);
1347 if (blocklen * 2 > sizeof(tmp)) {
1348 silc_cipher_free(aes);
1349 silc_sfree(stack, key);
1353 /* Allocate SHA1 hash */
1354 if (!silc_hash_alloc("sha1", &sha1)) {
1355 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1356 silc_sfree(stack, key);
1357 silc_cipher_free(aes);
1362 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1363 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1364 silc_sfree(stack, key);
1365 silc_hash_free(sha1);
1366 silc_cipher_free(aes);
1370 /* Derive the encryption key from the provided key material. The key
1371 is 256 bits length, and derived by taking hash of the data, then
1372 re-hashing the data and the previous digest, and using the first and
1373 second digest as the key. */
1374 silc_hash_init(sha1);
1375 silc_hash_update(sha1, passphrase, passphrase_len);
1376 silc_hash_final(sha1, keymat);
1377 silc_hash_init(sha1);
1378 silc_hash_update(sha1, passphrase, passphrase_len);
1379 silc_hash_update(sha1, keymat, 16);
1380 silc_hash_final(sha1, keymat + 16);
1382 /* Set the key to the cipher */
1383 silc_cipher_set_key(aes, keymat, 256, TRUE);
1385 /* Encode the buffer to be encrypted. Add padding to it too, at least
1386 block size of the cipher. */
1388 /* Allocate buffer for encryption */
1389 len = silc_hmac_len(sha1hmac);
1390 padlen = 16 + (16 - ((key_len + 4) % blocklen));
1391 enc = silc_buffer_salloc_size(stack, 4 + 4 + key_len + padlen + len);
1393 silc_sfree(stack, key);
1394 silc_hmac_free(sha1hmac);
1395 silc_hash_free(sha1);
1396 silc_cipher_free(aes);
1400 /* Generate padding */
1401 for (i = 0; i < padlen; i++)
1402 tmp[i] = silc_rng_get_byte_fast(rng);
1404 /* Put magic number */
1405 SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
1406 silc_buffer_pull(enc, 4);
1408 /* Encode the buffer */
1409 silc_buffer_sformat(stack, enc,
1410 SILC_STR_UI_INT(key_len),
1411 SILC_STR_UI_XNSTRING(key, key_len),
1412 SILC_STR_UI_XNSTRING(tmp, padlen),
1414 silc_sfree(stack, key);
1417 silc_cipher_encrypt(aes, enc->data, enc->data, silc_buffer_len(enc) - len,
1418 silc_cipher_get_iv(aes));
1420 silc_buffer_push(enc, 4);
1422 /* Compute HMAC over the encrypted data and append the MAC to data.
1423 The key is the first digest of the original key material. */
1424 key_len = silc_buffer_len(enc) - len;
1425 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1426 silc_hmac_update(sha1hmac, enc->data, key_len);
1427 silc_buffer_pull(enc, key_len);
1428 silc_hmac_final(sha1hmac, enc->data, NULL);
1429 silc_buffer_push(enc, key_len);
1432 memset(keymat, 0, sizeof(keymat));
1433 memset(tmp, 0, sizeof(tmp));
1434 silc_hmac_free(sha1hmac);
1435 silc_hash_free(sha1);
1436 silc_cipher_free(aes);
1439 case SILC_PKCS_FILE_BIN:
1442 case SILC_PKCS_FILE_BASE64:
1443 data = silc_base64_encode_file(stack, enc->data, silc_buffer_len(enc));
1445 silc_buffer_clear(enc);
1446 silc_buffer_sfree(stack, enc);
1449 silc_sfree(stack, silc_buffer_steal(enc, NULL));
1450 silc_buffer_set(enc, data, strlen(data));
1455 key_len = silc_buffer_len(enc);
1457 /* Encode the data and save to file */
1458 len = key_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1459 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1460 buf = silc_buffer_salloc_size(stack, len);
1462 silc_buffer_sfree(stack, enc);
1465 silc_buffer_sformat(stack, buf,
1466 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
1467 SILC_STR_UI_XNSTRING(key, key_len),
1468 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
1471 silc_buffer_sfree(stack, enc);
1472 data = silc_buffer_steal(buf, ret_len);
1473 silc_buffer_sfree(stack, buf);
1478 /* Exports private key as SILC implementation style private key */
1481 silc_pkcs_silc_export_private_key(const struct SilcPKCSObjectStruct *pkcs,
1484 SilcUInt32 *ret_len)
1486 SilcSILCPrivateKey silc_privkey = private_key;
1487 const SilcPKCSAlgorithm *alg = silc_privkey->pkcs;
1488 SilcBufferStruct alg_key;
1489 SilcBuffer buf = NULL;
1490 SilcAsn1 asn1 = NULL;
1491 unsigned char *prv = NULL, *key = NULL, *ret;
1492 SilcUInt32 prv_len, key_len, totlen;
1494 SILC_LOG_DEBUG(("Encoding SILC private key"));
1496 /* Export PKCS algorithm private key */
1497 if (alg->export_private_key)
1498 prv = alg->export_private_key(alg, stack,
1499 silc_privkey->private_key, &prv_len);
1502 silc_buffer_set(&alg_key, prv, prv_len);
1504 asn1 = silc_asn1_alloc(stack);
1508 if (!strcmp(alg->name, "rsa")) {
1509 /* Parse the PKCS #1 private key */
1510 SilcMPInt n, e, d, dp, dq, qp, p, q;
1511 SilcUInt32 e_len, n_len, d_len, dp_len, dq_len,
1512 qp_len, p_len, q_len, len = 0;
1513 unsigned char *nb, *eb, *db, *dpb, *dqb, *qpb, *pb, *qb;
1515 if (!silc_asn1_decode(asn1, &alg_key,
1517 SILC_ASN1_INT(NULL),
1526 SILC_ASN1_END, SILC_ASN1_END))
1529 /* Encode to SILC RSA private key */
1530 eb = silc_mp_mp2bin(&e, 0, &e_len);
1531 nb = silc_mp_mp2bin(&n, 0, &n_len);
1532 db = silc_mp_mp2bin(&d, 0, &d_len);
1533 dpb = silc_mp_mp2bin(&dp, 0, &dp_len);
1534 dqb = silc_mp_mp2bin(&dq, 0, &dq_len);
1535 qpb = silc_mp_mp2bin(&qp, 0, &qp_len);
1536 pb = silc_mp_mp2bin(&p, 0, &p_len);
1537 qb = silc_mp_mp2bin(&q, 0, &q_len);
1538 len = 4 + e_len + 4 + n_len + 4 + d_len + 4+ dp_len + 4 +
1539 dq_len + 4 + qp_len + 4 + p_len + 4 + q_len + 4;
1541 buf = silc_buffer_salloc_size(stack, len);
1544 if (silc_buffer_sformat(stack, buf,
1545 SILC_STR_UI_INT(SILC_PRIVATE_KEY_VERSION_1),
1546 SILC_STR_UI_INT(e_len),
1547 SILC_STR_UI_XNSTRING(eb, e_len),
1548 SILC_STR_UI_INT(n_len),
1549 SILC_STR_UI_XNSTRING(nb, n_len),
1550 SILC_STR_UI_INT(d_len),
1551 SILC_STR_UI_XNSTRING(db, d_len),
1552 SILC_STR_UI_INT(dp_len),
1553 SILC_STR_UI_XNSTRING(dpb, dp_len),
1554 SILC_STR_UI_INT(dq_len),
1555 SILC_STR_UI_XNSTRING(dqb, dq_len),
1556 SILC_STR_UI_INT(qp_len),
1557 SILC_STR_UI_XNSTRING(qpb, qp_len),
1558 SILC_STR_UI_INT(p_len),
1559 SILC_STR_UI_XNSTRING(pb, p_len),
1560 SILC_STR_UI_INT(q_len),
1561 SILC_STR_UI_XNSTRING(qb, q_len),
1565 key = silc_buffer_steal(buf, &key_len);
1566 silc_buffer_sfree(stack, buf);
1576 } else if (!strcmp(alg->name, "dsa")) {
1577 SILC_NOT_IMPLEMENTED("SILC DSA Private Key");
1581 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1585 /* Encode SILC private key */
1586 totlen = 2 + strlen(alg->name) + key_len;
1587 buf = silc_buffer_salloc_size(stack, totlen);
1590 if (silc_buffer_sformat(stack, buf,
1591 SILC_STR_UI_SHORT(strlen(alg->name)),
1592 SILC_STR_UI32_STRING(alg->name),
1593 SILC_STR_UI_XNSTRING(key, key_len),
1597 ret = silc_buffer_steal(buf, ret_len);
1598 silc_buffer_sfree(stack, buf);
1599 silc_sfree(stack, prv);
1600 silc_sfree(stack, key);
1601 silc_asn1_free(asn1);
1606 silc_sfree(stack, prv);
1607 silc_sfree(stack, key);
1608 silc_buffer_sfree(stack, buf);
1612 /* Return key length */
1615 silc_pkcs_silc_private_key_bitlen(const struct SilcPKCSObjectStruct *pkcs,
1618 SilcSILCPrivateKey silc_privkey = private_key;
1619 return silc_privkey->pkcs->private_key_bitlen(silc_privkey->pkcs,
1620 silc_privkey->private_key);
1623 /* Frees private key */
1625 void silc_pkcs_silc_private_key_free(const struct SilcPKCSObjectStruct *pkcs,
1628 SilcSILCPrivateKey silc_privkey = private_key;
1630 silc_privkey->pkcs->private_key_free(silc_privkey->pkcs,
1631 silc_privkey->private_key);
1632 silc_free(silc_privkey);
1636 /***************************** PKCS operations ******************************/
1638 /* Encrypts as specified in SILC protocol specification */
1641 silc_pkcs_silc_encrypt(const struct SilcPKCSObjectStruct *pkcs,
1646 SilcPKCSEncryptCb encrypt_cb,
1649 SilcSILCPublicKey silc_pubkey = public_key;
1651 if (!silc_pubkey->pkcs->encrypt) {
1652 encrypt_cb(FALSE, NULL, 0, context);
1656 return silc_pubkey->pkcs->encrypt(silc_pubkey->pkcs,
1657 silc_pubkey->public_key,
1658 src, src_len, rng, encrypt_cb, context);
1661 /* Decrypts as specified in SILC protocol specification */
1664 silc_pkcs_silc_decrypt(const struct SilcPKCSObjectStruct *pkcs,
1668 SilcPKCSDecryptCb decrypt_cb,
1671 SilcSILCPrivateKey silc_privkey = private_key;
1673 if (!silc_privkey->pkcs->decrypt) {
1674 decrypt_cb(FALSE, NULL, 0, context);
1678 return silc_privkey->pkcs->decrypt(silc_privkey->pkcs,
1679 silc_privkey->private_key,
1680 src, src_len, decrypt_cb, context);
1683 /* Signs as specified in SILC protocol specification */
1686 silc_pkcs_silc_sign(const struct SilcPKCSObjectStruct *pkcs,
1690 SilcBool compute_hash,
1692 SilcPKCSSignCb sign_cb,
1695 SilcSILCPrivateKey silc_privkey = private_key;
1697 if (!silc_privkey->pkcs->sign) {
1698 sign_cb(FALSE, NULL, 0, context);
1702 return silc_privkey->pkcs->sign(silc_privkey->pkcs,
1703 silc_privkey->private_key,
1709 /* Verifies as specified in SILC protocol specification */
1712 silc_pkcs_silc_verify(const struct SilcPKCSObjectStruct *pkcs,
1714 unsigned char *signature,
1715 SilcUInt32 signature_len,
1716 unsigned char *data,
1717 SilcUInt32 data_len,
1719 SilcPKCSVerifyCb verify_cb,
1722 SilcSILCPublicKey silc_pubkey = public_key;
1724 if (!silc_pubkey->pkcs->verify) {
1725 verify_cb(FALSE, context);
1729 return silc_pubkey->pkcs->verify(silc_pubkey->pkcs,
1730 silc_pubkey->public_key,
1731 signature, signature_len,
1732 data, data_len, hash,
1733 verify_cb, context);