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 = (SilcPKCSObject *)pkcs;
89 (*ret_public_key)->alg = alg;
90 (*ret_public_key)->public_key = pubkey;
92 /* Allocate private key */
93 *ret_private_key = silc_calloc(1, sizeof(**ret_private_key));
94 if (!(*ret_private_key)) {
97 silc_free(*ret_public_key);
100 (*ret_private_key)->pkcs = (SilcPKCSObject *)pkcs;
101 (*ret_private_key)->alg = alg;
102 (*ret_private_key)->private_key = privkey;
104 /* Generate the algorithm key pair */
105 if (!alg->generate_key(alg, bits_key_len, rng, &pubkey->public_key,
106 &privkey->private_key)) {
109 silc_free(*ret_public_key);
110 silc_free(*ret_private_key);
118 /**************************** Utility functions ******************************/
120 /* Decodes the provided `identifier' */
122 SilcBool silc_pkcs_silc_decode_identifier(const char *identifier,
123 SilcPublicKeyIdentifier ident)
128 /* Protocol says that at least UN and HN must be provided as identifier */
129 if (!strstr(identifier, "UN=") && !strstr(identifier, "HN=")) {
130 SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
135 cp = (char *)identifier;
137 len = strcspn(cp, ",");
142 if (len - 1 >= 0 && cp[len - 1] == '\\') {
144 if (len + 1 > strlen(cp)) {
149 len = strcspn(cp, ",") + len;
154 if (len - 1 >= 0 && cp[len - 1] != '\\')
162 item = silc_calloc(len + 1, sizeof(char));
165 if (len > strlen(cp))
167 memcpy(item, cp, len);
169 if (strstr(item, "UN="))
170 ident->username = strdup(item + strcspn(cp, "=") + 1);
171 else if (strstr(item, "HN="))
172 ident->host = strdup(item + strcspn(cp, "=") + 1);
173 else if (strstr(item, "RN="))
174 ident->realname = strdup(item + strcspn(cp, "=") + 1);
175 else if (strstr(item, "E="))
176 ident->email = strdup(item + strcspn(cp, "=") + 1);
177 else if (strstr(item, "O="))
178 ident->org = strdup(item + strcspn(cp, "=") + 1);
179 else if (strstr(item, "C="))
180 ident->country = strdup(item + strcspn(cp, "=") + 1);
181 else if (strstr(item, "V="))
182 ident->version = strdup(item + strcspn(cp, "=") + 1);
197 /* Encodes and returns SILC public key identifier. If some of the
198 arguments is NULL those are not encoded into the identifier string.
199 Protocol says that at least username and host must be provided. */
201 char *silc_pkcs_silc_encode_identifier(SilcStack stack,
202 char *username, char *host,
203 char *realname, char *email,
204 char *org, char *country,
207 SilcBufferStruct buf;
210 if (!username || !host)
212 if (strlen(username) < 3 || strlen(host) < 3)
215 memset(&buf, 0, sizeof(buf));
218 silc_buffer_sformat(stack, &buf,
220 SILC_STR_UI32_STRING("UN="),
221 SILC_STR_UI32_STRING(username),
225 silc_buffer_sformat(stack, &buf,
227 SILC_STR_UI32_STRING(", "),
228 SILC_STR_UI32_STRING("HN="),
229 SILC_STR_UI32_STRING(host),
233 silc_buffer_sformat(stack, &buf,
235 SILC_STR_UI32_STRING(", "),
236 SILC_STR_UI32_STRING("RN="),
237 SILC_STR_UI32_STRING(realname),
241 silc_buffer_sformat(stack, &buf,
243 SILC_STR_UI32_STRING(", "),
244 SILC_STR_UI32_STRING("E="),
245 SILC_STR_UI32_STRING(email),
249 silc_buffer_sformat(stack, &buf,
251 SILC_STR_UI32_STRING(", "),
252 SILC_STR_UI32_STRING("O="),
253 SILC_STR_UI32_STRING(org),
257 silc_buffer_sformat(stack, &buf,
259 SILC_STR_UI32_STRING(", "),
260 SILC_STR_UI32_STRING("C="),
261 SILC_STR_UI32_STRING(country),
265 if (strlen(version) > 1 || !isdigit(version[0])) {
266 silc_buffer_spurge(stack, &buf);
269 silc_buffer_sformat(stack, &buf,
271 SILC_STR_UI32_STRING(", "),
272 SILC_STR_UI32_STRING("V="),
273 SILC_STR_UI32_STRING(version),
277 silc_buffer_sformat(stack, &buf, SILC_STR_UI_CHAR(0), SILC_STR_END);
279 identifier = silc_buffer_steal(&buf, NULL);
283 /* Return SILC public key version */
285 int silc_pkcs_silc_public_key_version(SilcPublicKey public_key)
287 SilcSILCPublicKey silc_pubkey;
289 if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC)
292 silc_pubkey = public_key->public_key;
294 /* If version identifire is not present it is version 1. */
295 if (!silc_pubkey->identifier.version)
298 return atoi(silc_pubkey->identifier.version);
301 /*************************** Public key routines *****************************/
303 /* Returns PKCS algorithm context */
305 SILC_PKCS_GET_ALGORITHM(silc_pkcs_silc_get_algorithm)
307 SilcSILCPublicKey silc_pubkey = public_key;
308 return silc_pubkey->pkcs;
311 /* Imports SILC protocol style public key from SILC public key file */
313 SILC_PKCS_IMPORT_PUBLIC_KEY_FILE(silc_pkcs_silc_import_public_key_file)
316 unsigned char *data = NULL;
319 SILC_LOG_DEBUG(("Parsing SILC public key file"));
324 /* Check start of file and remove header from the data. */
325 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
326 if (filedata_len < len + strlen(SILC_PKCS_PUBLIC_KEYFILE_END)) {
327 SILC_LOG_ERROR(("Malformed SILC public key header"));
330 for (i = 0; i < len; i++) {
331 if (*filedata != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
332 SILC_LOG_ERROR(("Malformed SILC public key header"));
337 filedata_len -= (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
338 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
341 case SILC_PKCS_FILE_BIN:
344 case SILC_PKCS_FILE_BASE64:
345 data = silc_base64_decode(NULL, filedata, filedata_len, &filedata_len);
352 ret = silc_pkcs_silc_import_public_key(pkcs, filedata, filedata_len,
353 ret_public_key, ret_alg);
356 return ret ? TRUE : FALSE;
359 /* Imports SILC protocol style public key */
361 SILC_PKCS_IMPORT_PUBLIC_KEY(silc_pkcs_silc_import_public_key)
363 const SilcPKCSAlgorithm *alg;
364 SilcBufferStruct buf, alg_key;
365 SilcSILCPublicKey silc_pubkey = NULL;
366 SilcAsn1 asn1 = NULL;
367 SilcUInt32 totlen, keydata_len;
368 SilcUInt16 pkcs_len, identifier_len;
369 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
372 SILC_LOG_DEBUG(("Parsing SILC public key"));
377 silc_buffer_set(&buf, key, key_len);
380 ret = silc_buffer_unformat(&buf,
382 SILC_STR_UI_INT(&totlen),
387 /* Backwards compatibility */
388 if (totlen == key_len)
391 if (totlen + 4 != key_len)
394 /* Get algorithm name and identifier */
396 silc_buffer_unformat(&buf,
398 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
399 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
404 if (pkcs_len < 1 || identifier_len < 3 ||
405 pkcs_len + identifier_len > totlen)
409 keydata_len = silc_buffer_len(&buf);
410 ret = silc_buffer_unformat(&buf,
411 SILC_STR_DATA(&key_data, keydata_len),
416 /* Allocate SILC public key context */
417 silc_pubkey = silc_calloc(1, sizeof(*silc_pubkey));
421 /* Decode SILC identifier */
422 if (!silc_pkcs_silc_decode_identifier(ident, &silc_pubkey->identifier))
425 asn1 = silc_asn1_alloc(NULL);
429 SILC_LOG_DEBUG(("Public key version %s",
430 (!silc_pubkey->identifier.version ? "1" :
431 silc_pubkey->identifier.version)));
433 if (!strcmp(pkcs_name, "rsa")) {
434 /* Parse the SILC RSA public key */
435 SilcUInt32 e_len, n_len;
438 /* Get PKCS object. Different PKCS #1 scheme is used with different
440 if (!silc_pubkey->identifier.version ||
441 atoi(silc_pubkey->identifier.version) <= 1) {
443 alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid");
445 /* Version 2 and newer */
446 alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1");
449 SILC_LOG_DEBUG(("Unsupported PKCS algorithm: rsa"));
452 silc_pubkey->pkcs = alg;
456 SILC_GET32_MSB(e_len, key_data);
457 if (!e_len || e_len + 4 > keydata_len)
460 silc_mp_bin2mp(key_data + 4, e_len, &e);
461 if (keydata_len < 4 + e_len + 4) {
465 SILC_GET32_MSB(n_len, key_data + 4 + e_len);
466 if (!n_len || e_len + 4 + n_len + 4 > keydata_len) {
471 silc_mp_bin2mp(key_data + 4 + e_len + 4, n_len, &n);
473 /* Encode to PKCS #1 format */
474 memset(&alg_key, 0, sizeof(alg_key));
475 if (!silc_asn1_encode(asn1, &alg_key,
479 SILC_ASN1_END, SILC_ASN1_END)) {
488 } else if (!strcmp(pkcs_name, "dsa")) {
489 SILC_NOT_IMPLEMENTED("DSA SILC Public Key");
493 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
497 /* Import PKCS algorithm public key */
498 if (!alg->import_public_key(alg, alg_key.data, silc_buffer_len(&alg_key),
499 &silc_pubkey->public_key))
502 silc_free(pkcs_name);
504 silc_asn1_free(asn1);
506 *ret_public_key = silc_pubkey;
512 silc_free(pkcs_name);
514 silc_free(silc_pubkey);
516 silc_asn1_free(asn1);
520 /* Exports public key as SILC protocol style public key file */
522 SILC_PKCS_EXPORT_PUBLIC_KEY_FILE(silc_pkcs_silc_export_public_key_file)
525 unsigned char *key, *data;
528 SILC_LOG_DEBUG(("Encoding SILC public key file"));
531 key = silc_pkcs_silc_export_public_key(pkcs, stack, public_key, &key_len);
536 case SILC_PKCS_FILE_BIN:
539 case SILC_PKCS_FILE_BASE64:
540 data = silc_base64_encode_file(stack, key, key_len);
543 silc_sfree(stack, key);
545 key_len = strlen(data);
549 /* Encode SILC public key file */
550 buf = silc_buffer_salloc_size(stack, key_len +
551 (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
552 strlen(SILC_PKCS_PUBLIC_KEYFILE_END)));
554 silc_sfree(stack, key);
558 if (silc_buffer_sformat(stack, buf,
559 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
560 SILC_STR_UI_XNSTRING(key, key_len),
561 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
563 silc_buffer_sfree(stack, buf);
564 silc_sfree(stack, key);
568 silc_sfree(stack, key);
569 key = silc_buffer_steal(buf, ret_len);
570 silc_buffer_sfree(stack, buf);
575 /* Exports public key as SILC protocol style public key */
577 SILC_PKCS_EXPORT_PUBLIC_KEY(silc_pkcs_silc_export_public_key)
579 SilcSILCPublicKey silc_pubkey = public_key;
580 const SilcPKCSAlgorithm *alg = silc_pubkey->pkcs;
581 SilcBufferStruct alg_key;
582 SilcBuffer buf = NULL;
583 SilcAsn1 asn1 = NULL;
584 unsigned char *pk = NULL, *key = NULL, *ret;
585 SilcUInt32 pk_len, key_len, totlen;
588 SILC_LOG_DEBUG(("Encoding SILC public key"));
590 /* Export PKCS algorithm public key */
591 if (alg->export_public_key)
592 pk = alg->export_public_key(alg, stack, silc_pubkey->public_key, &pk_len);
594 SILC_LOG_ERROR(("Error exporting PKCS algorithm key"));
597 silc_buffer_set(&alg_key, pk, pk_len);
599 /* Encode identifier */
601 silc_pkcs_silc_encode_identifier(stack,
602 silc_pubkey->identifier.username,
603 silc_pubkey->identifier.host,
604 silc_pubkey->identifier.realname,
605 silc_pubkey->identifier.email,
606 silc_pubkey->identifier.org,
607 silc_pubkey->identifier.country,
608 silc_pubkey->identifier.version);
610 SILC_LOG_ERROR(("Error encoding SILC public key identifier"));
614 asn1 = silc_asn1_alloc(stack);
618 if (!strcmp(alg->name, "rsa")) {
619 /* Parse the PKCS #1 public key */
621 SilcUInt32 n_len, e_len;
622 unsigned char *nb, *eb;
624 memset(&n, 0, sizeof(n));
625 memset(&e, 0, sizeof(e));
626 if (!silc_asn1_decode(asn1, &alg_key,
630 SILC_ASN1_END, SILC_ASN1_END))
633 /* Encode to SILC RSA public key */
634 eb = silc_mp_mp2bin(&e, 0, &e_len);
637 nb = silc_mp_mp2bin(&n, 0, &n_len);
640 key_len = e_len + 4 + n_len + 4;
641 key = silc_scalloc(stack, key_len, sizeof(*key));
645 /* Put e length and e */
646 SILC_PUT32_MSB(e_len, key);
647 memcpy(key + 4, eb, e_len);
649 /* Put n length and n. */
650 SILC_PUT32_MSB(n_len, key + 4 + e_len);
651 memcpy(key + 4 + e_len + 4, nb, n_len);
656 } else if (!strcmp(alg->name, "dsa")) {
657 SILC_NOT_IMPLEMENTED("SILC DSA Public Key");
661 SILC_LOG_ERROR(("Unsupported PKCS algorithm: %s", alg->name));
665 /* Encode SILC Public Key */
666 totlen = 2 + strlen(alg->name) + 2 + strlen(identifier) + key_len;
667 buf = silc_buffer_salloc_size(stack, totlen + 4);
670 if (silc_buffer_sformat(stack, buf,
671 SILC_STR_UI_INT(totlen),
672 SILC_STR_UI_SHORT(strlen(alg->name)),
673 SILC_STR_UI32_STRING(alg->name),
674 SILC_STR_UI_SHORT(strlen(identifier)),
675 SILC_STR_UI32_STRING(identifier),
676 SILC_STR_UI_XNSTRING(key, key_len),
680 ret = silc_buffer_steal(buf, ret_len);
681 silc_buffer_sfree(stack, buf);
682 silc_sfree(stack, key);
683 silc_sfree(stack, identifier);
684 silc_buffer_spurge(stack, &alg_key);
685 silc_asn1_free(asn1);
690 silc_sfree(stack, identifier);
691 silc_sfree(stack, pk);
692 silc_sfree(stack, key);
693 silc_buffer_sfree(stack, buf);
695 silc_asn1_free(asn1);
699 /* Return key length */
701 SILC_PKCS_PUBLIC_KEY_BITLEN(silc_pkcs_silc_public_key_bitlen)
703 SilcSILCPublicKey silc_pubkey = public_key;
704 return silc_pubkey->pkcs->public_key_bitlen(silc_pubkey->pkcs,
705 silc_pubkey->public_key);
708 /* Copy public key */
710 SILC_PKCS_PUBLIC_KEY_COPY(silc_pkcs_silc_public_key_copy)
712 SilcSILCPublicKey silc_pubkey = public_key, new_pubkey;
713 SilcPublicKeyIdentifier ident = &silc_pubkey->identifier;
715 new_pubkey = silc_calloc(1, sizeof(*new_pubkey));
718 new_pubkey->pkcs = silc_pubkey->pkcs;
720 new_pubkey->public_key =
721 silc_pubkey->pkcs->public_key_copy(silc_pubkey->pkcs,
722 silc_pubkey->public_key);
723 if (!new_pubkey->public_key) {
724 silc_free(new_pubkey);
729 new_pubkey->identifier.username =
730 silc_memdup(ident->username, strlen(ident->username));
732 new_pubkey->identifier.host =
733 silc_memdup(ident->host, strlen(ident->host));
735 new_pubkey->identifier.realname =
736 silc_memdup(ident->realname, strlen(ident->realname));
738 new_pubkey->identifier.email =
739 silc_memdup(ident->email, strlen(ident->email));
741 new_pubkey->identifier.org =
742 silc_memdup(ident->org, strlen(ident->org));
744 new_pubkey->identifier.country =
745 silc_memdup(ident->country, strlen(ident->country));
747 new_pubkey->identifier.version =
748 silc_memdup(ident->version, strlen(ident->version));
753 /* Compares public keys */
755 SILC_PKCS_PUBLIC_KEY_COMPARE(silc_pkcs_silc_public_key_compare)
757 SilcSILCPublicKey k1 = key1, k2 = key2;
759 if (strcmp(k1->pkcs->name, k2->pkcs->name))
762 if ((k1->identifier.username && !k2->identifier.username) ||
763 (!k1->identifier.username && k2->identifier.username) ||
764 (k1->identifier.username && k2->identifier.username &&
765 strcmp(k1->identifier.username, k2->identifier.username)))
768 if ((k1->identifier.host && !k2->identifier.host) ||
769 (!k1->identifier.host && k2->identifier.host) ||
770 (k1->identifier.host && k2->identifier.host &&
771 strcmp(k1->identifier.host, k2->identifier.host)))
774 if ((k1->identifier.realname && !k2->identifier.realname) ||
775 (!k1->identifier.realname && k2->identifier.realname) ||
776 (k1->identifier.realname && k2->identifier.realname &&
777 strcmp(k1->identifier.realname, k2->identifier.realname)))
780 if ((k1->identifier.email && !k2->identifier.email) ||
781 (!k1->identifier.email && k2->identifier.email) ||
782 (k1->identifier.email && k2->identifier.email &&
783 strcmp(k1->identifier.email, k2->identifier.email)))
786 if ((k1->identifier.org && !k2->identifier.org) ||
787 (!k1->identifier.org && k2->identifier.org) ||
788 (k1->identifier.org && k2->identifier.org &&
789 strcmp(k1->identifier.org, k2->identifier.org)))
792 if ((k1->identifier.country && !k2->identifier.country) ||
793 (!k1->identifier.country && k2->identifier.country) ||
794 (k1->identifier.country && k2->identifier.country &&
795 strcmp(k1->identifier.country, k2->identifier.country)))
798 if ((k1->identifier.version && !k2->identifier.version) ||
799 (!k1->identifier.version && k2->identifier.version) ||
800 (k1->identifier.version && k2->identifier.version &&
801 strcmp(k1->identifier.version, k2->identifier.version)))
804 return k1->pkcs->public_key_compare(k1->pkcs, k1->public_key, k2->public_key);
807 /* Frees public key */
809 SILC_PKCS_PUBLIC_KEY_FREE(silc_pkcs_silc_public_key_free)
811 SilcSILCPublicKey silc_pubkey = public_key;
813 silc_pubkey->pkcs->public_key_free(silc_pubkey->pkcs,
814 silc_pubkey->public_key);
816 silc_free(silc_pubkey->identifier.username);
817 silc_free(silc_pubkey->identifier.host);
818 silc_free(silc_pubkey->identifier.realname);
819 silc_free(silc_pubkey->identifier.email);
820 silc_free(silc_pubkey->identifier.org);
821 silc_free(silc_pubkey->identifier.country);
822 silc_free(silc_pubkey->identifier.version);
823 silc_free(silc_pubkey);
827 /*************************** Private key routines ****************************/
829 /* Private key file magic */
830 #define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
832 /* Imports SILC implementation style private key file */
834 SILC_PKCS_IMPORT_PRIVATE_KEY_FILE(silc_pkcs_silc_import_private_key_file)
840 unsigned char tmp[32], keymat[64], *data = NULL;
841 SilcUInt32 i, len, magic, mac_len;
844 SILC_LOG_DEBUG(("Parsing SILC private key file"));
846 /* Check start of file and remove header from the data. */
847 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
848 if (filedata_len < len + strlen(SILC_PKCS_PRIVATE_KEYFILE_END)) {
849 SILC_LOG_ERROR(("Malformed SILC private key header"));
852 for (i = 0; i < len; i++) {
853 if (*filedata != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
854 SILC_LOG_ERROR(("Malformed SILC private key header"));
860 len = filedata_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
861 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
864 case SILC_PKCS_FILE_BIN:
867 case SILC_PKCS_FILE_BASE64:
868 data = silc_base64_decode(NULL, filedata, filedata_len, &len);
875 memset(tmp, 0, sizeof(tmp));
876 memset(keymat, 0, sizeof(keymat));
878 /* Check file magic */
879 SILC_GET32_MSB(magic, filedata);
880 if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
881 SILC_LOG_DEBUG(("Private key does not have correct magic"));
885 /* Allocate the AES cipher */
886 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
887 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
890 blocklen = silc_cipher_get_block_len(aes);
891 if (blocklen * 2 > sizeof(tmp)) {
892 silc_cipher_free(aes);
896 /* Allocate SHA1 hash */
897 if (!silc_hash_alloc("sha1", &sha1)) {
898 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
899 silc_cipher_free(aes);
904 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
905 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
906 silc_hash_free(sha1);
907 silc_cipher_free(aes);
911 /* Derive the decryption key from the provided key material. The key
912 is 256 bits length, and derived by taking hash of the data, then
913 re-hashing the data and the previous digest, and using the first and
914 second digest as the key. */
915 silc_hash_init(sha1);
916 silc_hash_update(sha1, passphrase, passphrase_len);
917 silc_hash_final(sha1, keymat);
918 silc_hash_init(sha1);
919 silc_hash_update(sha1, passphrase, passphrase_len);
920 silc_hash_update(sha1, keymat, 16);
921 silc_hash_final(sha1, keymat + 16);
923 /* Set the key to the cipher */
924 silc_cipher_set_key(aes, keymat, 256, FALSE);
926 /* First, verify the MAC of the private key data */
927 mac_len = silc_hmac_len(sha1hmac);
928 silc_hmac_init_with_key(sha1hmac, keymat, 16);
929 silc_hmac_update(sha1hmac, filedata, len - mac_len);
930 silc_hmac_final(sha1hmac, tmp, NULL);
931 if (memcmp(tmp, filedata + (len - mac_len), mac_len)) {
932 SILC_LOG_DEBUG(("Integrity check for private key failed"));
933 memset(keymat, 0, sizeof(keymat));
934 memset(tmp, 0, sizeof(tmp));
935 silc_hmac_free(sha1hmac);
936 silc_hash_free(sha1);
937 silc_cipher_free(aes);
943 /* Decrypt the private key buffer */
944 silc_cipher_decrypt(aes, filedata, filedata, len - mac_len, NULL);
945 SILC_GET32_MSB(i, filedata);
947 SILC_LOG_DEBUG(("Bad private key length in buffer!"));
948 memset(keymat, 0, sizeof(keymat));
949 memset(tmp, 0, sizeof(tmp));
950 silc_hmac_free(sha1hmac);
951 silc_hash_free(sha1);
952 silc_cipher_free(aes);
959 memset(keymat, 0, sizeof(keymat));
960 memset(tmp, 0, sizeof(tmp));
961 silc_hmac_free(sha1hmac);
962 silc_hash_free(sha1);
963 silc_cipher_free(aes);
965 /* Import the private key */
966 ret = silc_pkcs_silc_import_private_key(pkcs, filedata, len, ret_private_key,
971 return ret ? TRUE : FALSE;
974 /* Private key version */
975 #define SILC_PRIVATE_KEY_VERSION_1 0x82171273
976 #define SILC_PRIVATE_KEY_VERSION_2 0xf911a3d1
978 /* Imports SILC implementation style private key */
980 SILC_PKCS_IMPORT_PRIVATE_KEY(silc_pkcs_silc_import_private_key)
982 SilcBufferStruct buf;
983 const SilcPKCSAlgorithm *alg;
984 SilcBufferStruct alg_key;
985 SilcSILCPrivateKey silc_privkey = NULL;
986 SilcAsn1 asn1 = NULL;
988 SilcUInt32 keydata_len;
989 unsigned char *pkcs_name = NULL, *key_data;
992 SILC_LOG_DEBUG(("Parsing SILC private key"));
994 if (!ret_private_key)
997 silc_buffer_set(&buf, (unsigned char *)key, key_len);
999 /* Get algorithm name and identifier */
1001 silc_buffer_unformat(&buf,
1002 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
1005 SILC_LOG_DEBUG(("Cannot decode private key buffer"));
1009 if (pkcs_len < 1 || pkcs_len > silc_buffer_truelen(&buf)) {
1010 SILC_LOG_DEBUG(("Malformed private key buffer"));
1014 /* Get key data. We assume that rest of the buffer is key data. */
1015 silc_buffer_pull(&buf, 2 + pkcs_len);
1016 keydata_len = silc_buffer_len(&buf);
1017 ret = silc_buffer_unformat(&buf,
1018 SILC_STR_UI_XNSTRING(&key_data, keydata_len),
1023 /* Allocate SILC private key context */
1024 silc_privkey = silc_calloc(1, sizeof(*silc_privkey));
1028 asn1 = silc_asn1_alloc(NULL);
1032 if (!strcmp(pkcs_name, "rsa")) {
1033 /* Parse the RSA SILC private key */
1035 SilcMPInt n, e, d, dp, dq, qp, p, q;
1037 SilcUInt32 len, ver;
1039 if (keydata_len < 4)
1041 silc_buffer_set(&k, key_data, keydata_len);
1043 /* Get version. Key without the version is old style private key
1044 and we need to do some computation to get it to correct format. */
1045 if (silc_buffer_unformat(&k,
1046 SILC_STR_UI_INT(&ver),
1049 silc_buffer_pull(&k, 4);
1051 if (ver != SILC_PRIVATE_KEY_VERSION_1 &&
1052 ver != SILC_PRIVATE_KEY_VERSION_2) {
1056 if (silc_buffer_unformat(&k,
1057 SILC_STR_UI_INT(&len),
1060 silc_buffer_pull(&k, 4);
1063 /* Get PKCS object. Different PKCS #1 scheme is used with different
1065 if (ver == 0 || ver == SILC_PRIVATE_KEY_VERSION_1) {
1066 /* Version 0 and 1 */
1067 alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid");
1069 /* Version 2 and newer */
1070 alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1");
1073 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1076 silc_privkey->pkcs = alg;
1078 SILC_LOG_DEBUG(("Private key version %s",
1079 (ver == SILC_PRIVATE_KEY_VERSION_1 ? "1" :
1080 ver == SILC_PRIVATE_KEY_VERSION_2 ? "2" : "0")));
1083 if (silc_buffer_unformat(&k,
1084 SILC_STR_DATA(&tmp, len),
1088 silc_mp_bin2mp(tmp, len, &e);
1089 silc_buffer_pull(&k, len);
1092 if (silc_buffer_unformat(&k,
1093 SILC_STR_UI_INT(&len),
1096 silc_buffer_pull(&k, 4);
1097 if (silc_buffer_unformat(&k,
1098 SILC_STR_DATA(&tmp, len),
1102 silc_mp_bin2mp(tmp, len, &n);
1103 silc_buffer_pull(&k, len);
1106 if (silc_buffer_unformat(&k,
1107 SILC_STR_UI_INT(&len),
1110 silc_buffer_pull(&k, 4);
1111 if (silc_buffer_unformat(&k,
1112 SILC_STR_DATA(&tmp, len),
1116 silc_mp_bin2mp(tmp, len, &d);
1117 silc_buffer_pull(&k, len);
1120 if (silc_buffer_unformat(&k,
1121 SILC_STR_UI_INT(&len),
1124 silc_buffer_pull(&k, 4);
1125 if (silc_buffer_unformat(&k,
1126 SILC_STR_DATA(&tmp, len),
1130 silc_mp_bin2mp(tmp, len, &dp);
1131 silc_buffer_pull(&k, len);
1134 if (silc_buffer_unformat(&k,
1135 SILC_STR_UI_INT(&len),
1138 silc_buffer_pull(&k, 4);
1139 if (silc_buffer_unformat(&k,
1140 SILC_STR_DATA(&tmp, len),
1144 silc_mp_bin2mp(tmp, len, &dq);
1145 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_len(&k) < len)
1158 silc_buffer_pull(&k, len);
1161 if (silc_buffer_unformat(&k,
1162 SILC_STR_UI_INT(&len),
1165 silc_buffer_pull(&k, 4);
1166 if (silc_buffer_len(&k) < len)
1168 silc_buffer_pull(&k, len);
1173 if (silc_buffer_unformat(&k,
1174 SILC_STR_UI_INT(&len),
1177 silc_buffer_pull(&k, 4);
1178 if (silc_buffer_unformat(&k,
1179 SILC_STR_DATA(&tmp, len),
1183 silc_mp_bin2mp(tmp, len, &qp);
1184 silc_buffer_pull(&k, len);
1188 if (silc_buffer_unformat(&k,
1189 SILC_STR_UI_INT(&len),
1192 silc_buffer_pull(&k, 4);
1193 if (silc_buffer_unformat(&k,
1194 SILC_STR_DATA(&tmp, len),
1198 silc_mp_bin2mp(tmp, len, &p);
1199 silc_buffer_pull(&k, len);
1202 if (silc_buffer_unformat(&k,
1203 SILC_STR_UI_INT(&len),
1206 silc_buffer_pull(&k, 4);
1207 if (silc_buffer_unformat(&k,
1208 SILC_STR_DATA(&tmp, len),
1212 silc_mp_bin2mp(tmp, len, &q);
1213 silc_buffer_pull(&k, len);
1216 /* Old version. Compute to new version */
1217 SILC_LOG_DEBUG(("Old version private key"));
1219 silc_mp_modinv(&qp, &q, &p);
1222 /* Encode to PKCS #1 format */
1223 memset(&alg_key, 0, sizeof(alg_key));
1224 if (!silc_asn1_encode(asn1, &alg_key,
1226 SILC_ASN1_SHORT_INT(0),
1235 SILC_ASN1_END, SILC_ASN1_END))
1244 silc_mp_uninit(&dp);
1245 silc_mp_uninit(&dq);
1246 silc_mp_uninit(&qp);
1248 } else if (!strcmp(pkcs_name, "dsa")) {
1249 SILC_NOT_IMPLEMENTED("DSA SILC Private Key");
1253 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1257 /* Import PKCS algorithm private key */
1258 if (!alg->import_private_key(alg, alg_key.data, silc_buffer_len(&alg_key),
1259 &silc_privkey->private_key))
1262 silc_free(pkcs_name);
1263 silc_asn1_free(asn1);
1265 *ret_private_key = silc_privkey;
1271 silc_free(pkcs_name);
1272 silc_free(silc_privkey);
1274 silc_asn1_free(asn1);
1275 SILC_LOG_ERROR(("Malformed SILC private key "));
1279 /* Exports private key as SILC implementation style private key file */
1281 SILC_PKCS_EXPORT_PRIVATE_KEY_FILE(silc_pkcs_silc_export_private_key_file)
1286 SilcBuffer buf, enc;
1287 SilcUInt32 len, blocklen, padlen, key_len;
1288 unsigned char *key, *data;
1289 unsigned char tmp[32], keymat[64];
1292 SILC_LOG_DEBUG(("Encoding SILC private key file"));
1294 /* Export the private key */
1295 key = silc_pkcs_silc_export_private_key(pkcs, stack, private_key, &key_len);
1299 memset(tmp, 0, sizeof(tmp));
1300 memset(keymat, 0, sizeof(keymat));
1302 /* Allocate the AES cipher */
1303 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1304 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1305 silc_sfree(stack, key);
1308 blocklen = silc_cipher_get_block_len(aes);
1309 if (blocklen * 2 > sizeof(tmp)) {
1310 silc_cipher_free(aes);
1311 silc_sfree(stack, key);
1315 /* Allocate SHA1 hash */
1316 if (!silc_hash_alloc("sha1", &sha1)) {
1317 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1318 silc_sfree(stack, key);
1319 silc_cipher_free(aes);
1324 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1325 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1326 silc_sfree(stack, key);
1327 silc_hash_free(sha1);
1328 silc_cipher_free(aes);
1332 /* Derive the encryption key from the provided key material. The key
1333 is 256 bits length, and derived by taking hash of the data, then
1334 re-hashing the data and the previous digest, and using the first and
1335 second digest as the key. */
1336 silc_hash_init(sha1);
1337 silc_hash_update(sha1, passphrase, passphrase_len);
1338 silc_hash_final(sha1, keymat);
1339 silc_hash_init(sha1);
1340 silc_hash_update(sha1, passphrase, passphrase_len);
1341 silc_hash_update(sha1, keymat, 16);
1342 silc_hash_final(sha1, keymat + 16);
1344 /* Set the key to the cipher */
1345 silc_cipher_set_key(aes, keymat, 256, TRUE);
1347 /* Encode the buffer to be encrypted. Add padding to it too, at least
1348 block size of the cipher. */
1350 /* Allocate buffer for encryption */
1351 len = silc_hmac_len(sha1hmac);
1352 padlen = 16 + (16 - ((key_len + 4) % blocklen));
1353 enc = silc_buffer_salloc_size(stack, 4 + 4 + key_len + padlen + len);
1355 silc_sfree(stack, key);
1356 silc_hmac_free(sha1hmac);
1357 silc_hash_free(sha1);
1358 silc_cipher_free(aes);
1362 /* Generate padding */
1363 for (i = 0; i < padlen; i++)
1364 tmp[i] = silc_rng_get_byte_fast(rng);
1366 /* Put magic number */
1367 SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
1368 silc_buffer_pull(enc, 4);
1370 /* Encode the buffer */
1371 silc_buffer_sformat(stack, enc,
1372 SILC_STR_UI_INT(key_len),
1373 SILC_STR_UI_XNSTRING(key, key_len),
1374 SILC_STR_UI_XNSTRING(tmp, padlen),
1376 silc_sfree(stack, key);
1379 silc_cipher_encrypt(aes, enc->data, enc->data, silc_buffer_len(enc) - len,
1380 silc_cipher_get_iv(aes));
1382 silc_buffer_push(enc, 4);
1384 /* Compute HMAC over the encrypted data and append the MAC to data.
1385 The key is the first digest of the original key material. */
1386 key_len = silc_buffer_len(enc) - len;
1387 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1388 silc_hmac_update(sha1hmac, enc->data, key_len);
1389 silc_buffer_pull(enc, key_len);
1390 silc_hmac_final(sha1hmac, enc->data, NULL);
1391 silc_buffer_push(enc, key_len);
1394 memset(keymat, 0, sizeof(keymat));
1395 memset(tmp, 0, sizeof(tmp));
1396 silc_hmac_free(sha1hmac);
1397 silc_hash_free(sha1);
1398 silc_cipher_free(aes);
1401 case SILC_PKCS_FILE_BIN:
1404 case SILC_PKCS_FILE_BASE64:
1405 data = silc_base64_encode_file(stack, enc->data, silc_buffer_len(enc));
1407 silc_buffer_clear(enc);
1408 silc_buffer_sfree(stack, enc);
1411 silc_sfree(stack, silc_buffer_steal(enc, NULL));
1412 silc_buffer_set(enc, data, strlen(data));
1417 key_len = silc_buffer_len(enc);
1419 /* Encode the data and save to file */
1420 len = key_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1421 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1422 buf = silc_buffer_salloc_size(stack, len);
1424 silc_buffer_sfree(stack, enc);
1427 silc_buffer_sformat(stack, buf,
1428 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
1429 SILC_STR_UI_XNSTRING(key, key_len),
1430 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
1433 silc_buffer_sfree(stack, enc);
1434 data = silc_buffer_steal(buf, ret_len);
1435 silc_buffer_sfree(stack, buf);
1440 /* Exports private key as SILC implementation style private key */
1442 SILC_PKCS_EXPORT_PRIVATE_KEY(silc_pkcs_silc_export_private_key)
1444 SilcSILCPrivateKey silc_privkey = private_key;
1445 const SilcPKCSAlgorithm *alg = silc_privkey->pkcs;
1446 SilcBufferStruct alg_key;
1447 SilcBuffer buf = NULL;
1448 SilcAsn1 asn1 = NULL;
1449 unsigned char *prv = NULL, *key = NULL, *ret;
1450 SilcUInt32 prv_len, key_len, totlen;
1452 SILC_LOG_DEBUG(("Encoding SILC private key"));
1454 /* Export PKCS algorithm private key */
1455 if (alg->export_private_key)
1456 prv = alg->export_private_key(alg, stack,
1457 silc_privkey->private_key, &prv_len);
1460 silc_buffer_set(&alg_key, prv, prv_len);
1462 asn1 = silc_asn1_alloc(stack);
1466 if (!strcmp(alg->name, "rsa")) {
1467 /* Parse the PKCS #1 private key */
1468 SilcMPInt n, e, d, dp, dq, qp, p, q;
1469 SilcUInt32 e_len, n_len, d_len, dp_len, dq_len,
1470 qp_len, p_len, q_len, len = 0;
1471 unsigned char *nb, *eb, *db, *dpb, *dqb, *qpb, *pb, *qb;
1473 if (!silc_asn1_decode(asn1, &alg_key,
1475 SILC_ASN1_INT(NULL),
1484 SILC_ASN1_END, SILC_ASN1_END))
1487 /* Encode to SILC RSA private key */
1488 eb = silc_mp_mp2bin(&e, 0, &e_len);
1489 nb = silc_mp_mp2bin(&n, 0, &n_len);
1490 db = silc_mp_mp2bin(&d, 0, &d_len);
1491 dpb = silc_mp_mp2bin(&dp, 0, &dp_len);
1492 dqb = silc_mp_mp2bin(&dq, 0, &dq_len);
1493 qpb = silc_mp_mp2bin(&qp, 0, &qp_len);
1494 pb = silc_mp_mp2bin(&p, 0, &p_len);
1495 qb = silc_mp_mp2bin(&q, 0, &q_len);
1496 len = 4 + e_len + 4 + n_len + 4 + d_len + 4+ dp_len + 4 +
1497 dq_len + 4 + qp_len + 4 + p_len + 4 + q_len + 4;
1499 buf = silc_buffer_salloc_size(stack, len);
1502 if (silc_buffer_sformat(stack, buf,
1503 SILC_STR_UI_INT(SILC_PRIVATE_KEY_VERSION_1),
1504 SILC_STR_UI_INT(e_len),
1505 SILC_STR_UI_XNSTRING(eb, e_len),
1506 SILC_STR_UI_INT(n_len),
1507 SILC_STR_UI_XNSTRING(nb, n_len),
1508 SILC_STR_UI_INT(d_len),
1509 SILC_STR_UI_XNSTRING(db, d_len),
1510 SILC_STR_UI_INT(dp_len),
1511 SILC_STR_UI_XNSTRING(dpb, dp_len),
1512 SILC_STR_UI_INT(dq_len),
1513 SILC_STR_UI_XNSTRING(dqb, dq_len),
1514 SILC_STR_UI_INT(qp_len),
1515 SILC_STR_UI_XNSTRING(qpb, qp_len),
1516 SILC_STR_UI_INT(p_len),
1517 SILC_STR_UI_XNSTRING(pb, p_len),
1518 SILC_STR_UI_INT(q_len),
1519 SILC_STR_UI_XNSTRING(qb, q_len),
1523 key = silc_buffer_steal(buf, &key_len);
1524 silc_buffer_sfree(stack, buf);
1534 } else if (!strcmp(alg->name, "dsa")) {
1535 SILC_NOT_IMPLEMENTED("SILC DSA Private Key");
1539 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1543 /* Encode SILC private key */
1544 totlen = 2 + strlen(alg->name) + key_len;
1545 buf = silc_buffer_salloc_size(stack, totlen);
1548 if (silc_buffer_sformat(stack, buf,
1549 SILC_STR_UI_SHORT(strlen(alg->name)),
1550 SILC_STR_UI32_STRING(alg->name),
1551 SILC_STR_UI_XNSTRING(key, key_len),
1555 ret = silc_buffer_steal(buf, ret_len);
1556 silc_buffer_sfree(stack, buf);
1557 silc_sfree(stack, prv);
1558 silc_sfree(stack, key);
1559 silc_asn1_free(asn1);
1564 silc_sfree(stack, prv);
1565 silc_sfree(stack, key);
1566 silc_buffer_sfree(stack, buf);
1570 /* Return key length */
1572 SILC_PKCS_PRIVATE_KEY_BITLEN(silc_pkcs_silc_private_key_bitlen)
1574 SilcSILCPrivateKey silc_privkey = private_key;
1575 return silc_privkey->pkcs->private_key_bitlen(silc_privkey->pkcs,
1576 silc_privkey->private_key);
1579 /* Frees private key */
1581 SILC_PKCS_PRIVATE_KEY_FREE(silc_pkcs_silc_private_key_free)
1583 SilcSILCPrivateKey silc_privkey = private_key;
1585 silc_privkey->pkcs->private_key_free(silc_privkey->pkcs,
1586 silc_privkey->private_key);
1587 silc_free(silc_privkey);
1591 /***************************** PKCS operations ******************************/
1593 /* Encrypts as specified in SILC protocol specification */
1595 SILC_PKCS_ENCRYPT(silc_pkcs_silc_encrypt)
1597 SilcSILCPublicKey silc_pubkey = public_key;
1599 if (!silc_pubkey->pkcs->encrypt) {
1600 encrypt_cb(FALSE, NULL, 0, context);
1604 return silc_pubkey->pkcs->encrypt(silc_pubkey->pkcs,
1605 silc_pubkey->public_key,
1606 src, src_len, rng, encrypt_cb, context);
1609 /* Decrypts as specified in SILC protocol specification */
1611 SILC_PKCS_DECRYPT(silc_pkcs_silc_decrypt)
1613 SilcSILCPrivateKey silc_privkey = private_key;
1615 if (!silc_privkey->pkcs->decrypt) {
1616 decrypt_cb(FALSE, NULL, 0, context);
1620 return silc_privkey->pkcs->decrypt(silc_privkey->pkcs,
1621 silc_privkey->private_key,
1622 src, src_len, decrypt_cb, context);
1625 /* Signs as specified in SILC protocol specification */
1627 SILC_PKCS_SIGN(silc_pkcs_silc_sign)
1629 SilcSILCPrivateKey silc_privkey = private_key;
1631 if (!silc_privkey->pkcs->sign) {
1632 sign_cb(FALSE, NULL, 0, context);
1636 return silc_privkey->pkcs->sign(silc_privkey->pkcs,
1637 silc_privkey->private_key,
1643 /* Verifies as specified in SILC protocol specification */
1645 SILC_PKCS_VERIFY(silc_pkcs_silc_verify)
1647 SilcSILCPublicKey silc_pubkey = public_key;
1649 if (!silc_pubkey->pkcs->verify) {
1650 verify_cb(FALSE, context);
1654 return silc_pubkey->pkcs->verify(silc_pubkey->pkcs,
1655 silc_pubkey->public_key,
1656 signature, signature_len,
1657 data, data_len, hash,
1658 verify_cb, context);