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) < 1 || strlen(host) < 1)
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_DEBUG(("Malformed SILC public key header"));
330 for (i = 0; i < len; i++) {
331 if (*filedata != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
332 SILC_LOG_DEBUG(("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, NULL, 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 SilcBufferStruct buf, alg_key;
364 SilcSILCPublicKey silc_pubkey = NULL;
365 SilcAsn1 asn1 = NULL;
366 SilcUInt32 totlen, keydata_len;
367 SilcUInt16 pkcs_len, identifier_len;
368 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
371 SILC_LOG_DEBUG(("Parsing SILC public key"));
376 silc_buffer_set(&buf, key, key_len);
379 ret = silc_buffer_unformat(&buf,
381 SILC_STR_UI_INT(&totlen),
386 /* Backwards compatibility */
387 if (totlen == key_len)
390 if (totlen + 4 != key_len)
393 /* Get algorithm name and identifier */
395 silc_buffer_unformat(&buf,
397 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
398 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
403 if (pkcs_len < 1 || identifier_len < 3 ||
404 pkcs_len + identifier_len > totlen)
408 keydata_len = silc_buffer_len(&buf);
409 ret = silc_buffer_unformat(&buf,
410 SILC_STR_DATA(&key_data, keydata_len),
415 /* Allocate SILC public key context */
416 silc_pubkey = silc_calloc(1, sizeof(*silc_pubkey));
420 /* Decode SILC identifier */
421 if (!silc_pkcs_silc_decode_identifier(ident, &silc_pubkey->identifier))
424 asn1 = silc_asn1_alloc(NULL);
428 SILC_LOG_DEBUG(("Public key version %s",
429 (!silc_pubkey->identifier.version ? "1" :
430 silc_pubkey->identifier.version)));
432 if (!strcmp(pkcs_name, "rsa")) {
433 /* Parse the SILC RSA public key */
434 SilcUInt32 e_len, n_len;
437 /* Get PKCS object. Different PKCS #1 scheme is used with different
439 if (!silc_pubkey->identifier.version ||
440 atoi(silc_pubkey->identifier.version) <= 1) {
442 alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid");
444 /* Version 2 and newer */
445 alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1");
448 SILC_LOG_DEBUG(("Unsupported PKCS algorithm: rsa"));
451 silc_pubkey->pkcs = alg;
455 SILC_GET32_MSB(e_len, key_data);
456 if (!e_len || e_len + 4 > keydata_len)
459 silc_mp_bin2mp(key_data + 4, e_len, &e);
460 if (keydata_len < 4 + e_len + 4) {
464 SILC_GET32_MSB(n_len, key_data + 4 + e_len);
465 if (!n_len || e_len + 4 + n_len + 4 > keydata_len) {
470 silc_mp_bin2mp(key_data + 4 + e_len + 4, n_len, &n);
472 /* Encode to PKCS #1 format */
473 memset(&alg_key, 0, sizeof(alg_key));
474 if (!silc_asn1_encode(asn1, &alg_key,
478 SILC_ASN1_END, SILC_ASN1_END)) {
487 } else if (!strcmp(pkcs_name, "dsa")) {
488 SILC_NOT_IMPLEMENTED("DSA SILC Public Key");
492 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
496 /* Import PKCS algorithm public key */
497 if (!alg->import_public_key(alg, alg_key.data, silc_buffer_len(&alg_key),
498 &silc_pubkey->public_key))
501 silc_free(pkcs_name);
503 silc_asn1_free(asn1);
505 *ret_public_key = silc_pubkey;
511 silc_free(pkcs_name);
513 silc_free(silc_pubkey);
515 silc_asn1_free(asn1);
519 /* Exports public key as SILC protocol style public key file */
521 SILC_PKCS_EXPORT_PUBLIC_KEY_FILE(silc_pkcs_silc_export_public_key_file)
524 unsigned char *key, *data;
527 SILC_LOG_DEBUG(("Encoding SILC public key file"));
530 key = silc_pkcs_silc_export_public_key(pkcs, stack, public_key, &key_len);
535 case SILC_PKCS_FILE_BIN:
538 case SILC_PKCS_FILE_BASE64:
539 data = silc_base64_encode_file(stack, key, key_len);
542 silc_sfree(stack, key);
544 key_len = strlen(data);
548 /* Encode SILC public key file */
549 buf = silc_buffer_salloc_size(stack, key_len +
550 (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
551 strlen(SILC_PKCS_PUBLIC_KEYFILE_END)));
553 silc_sfree(stack, key);
557 if (silc_buffer_sformat(stack, buf,
558 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
559 SILC_STR_UI_XNSTRING(key, key_len),
560 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
562 silc_buffer_sfree(stack, buf);
563 silc_sfree(stack, key);
567 silc_sfree(stack, key);
568 key = silc_buffer_steal(buf, ret_len);
569 silc_buffer_sfree(stack, buf);
574 /* Exports public key as SILC protocol style public key */
576 SILC_PKCS_EXPORT_PUBLIC_KEY(silc_pkcs_silc_export_public_key)
578 SilcSILCPublicKey silc_pubkey = public_key;
579 const SilcPKCSAlgorithm *alg = silc_pubkey->pkcs;
580 SilcBufferStruct alg_key;
581 SilcBuffer buf = NULL;
582 SilcAsn1 asn1 = NULL;
583 unsigned char *pk = NULL, *key = NULL, *ret;
584 SilcUInt32 pk_len, key_len, totlen;
587 SILC_LOG_DEBUG(("Encoding SILC public key"));
589 /* Export PKCS algorithm public key */
590 if (alg->export_public_key)
591 pk = alg->export_public_key(alg, stack, silc_pubkey->public_key, &pk_len);
593 SILC_LOG_ERROR(("Error exporting PKCS algorithm key"));
596 silc_buffer_set(&alg_key, pk, pk_len);
598 /* Encode identifier */
600 silc_pkcs_silc_encode_identifier(stack,
601 silc_pubkey->identifier.username,
602 silc_pubkey->identifier.host,
603 silc_pubkey->identifier.realname,
604 silc_pubkey->identifier.email,
605 silc_pubkey->identifier.org,
606 silc_pubkey->identifier.country,
607 silc_pubkey->identifier.version);
609 SILC_LOG_ERROR(("Error encoding SILC public key identifier"));
613 asn1 = silc_asn1_alloc(stack);
617 if (!strcmp(alg->name, "rsa")) {
618 /* Parse the PKCS #1 public key */
620 SilcUInt32 n_len, e_len;
621 unsigned char *nb, *eb;
623 memset(&n, 0, sizeof(n));
624 memset(&e, 0, sizeof(e));
625 if (!silc_asn1_decode(asn1, &alg_key,
629 SILC_ASN1_END, SILC_ASN1_END))
632 /* Encode to SILC RSA public key */
633 eb = silc_mp_mp2bin(&e, 0, &e_len);
636 nb = silc_mp_mp2bin(&n, 0, &n_len);
639 key_len = e_len + 4 + n_len + 4;
640 key = silc_scalloc(stack, key_len, sizeof(*key));
644 /* Put e length and e */
645 SILC_PUT32_MSB(e_len, key);
646 memcpy(key + 4, eb, e_len);
648 /* Put n length and n. */
649 SILC_PUT32_MSB(n_len, key + 4 + e_len);
650 memcpy(key + 4 + e_len + 4, nb, n_len);
655 } else if (!strcmp(alg->name, "dsa")) {
656 SILC_NOT_IMPLEMENTED("SILC DSA Public Key");
660 SILC_LOG_ERROR(("Unsupported PKCS algorithm: %s", alg->name));
664 /* Encode SILC Public Key */
665 totlen = 2 + strlen(alg->name) + 2 + strlen(identifier) + key_len;
666 buf = silc_buffer_salloc_size(stack, totlen + 4);
669 if (silc_buffer_sformat(stack, buf,
670 SILC_STR_UI_INT(totlen),
671 SILC_STR_UI_SHORT(strlen(alg->name)),
672 SILC_STR_UI32_STRING(alg->name),
673 SILC_STR_UI_SHORT(strlen(identifier)),
674 SILC_STR_UI32_STRING(identifier),
675 SILC_STR_UI_XNSTRING(key, key_len),
679 ret = silc_buffer_steal(buf, ret_len);
680 silc_buffer_sfree(stack, buf);
681 silc_sfree(stack, key);
682 silc_sfree(stack, identifier);
683 silc_buffer_spurge(stack, &alg_key);
684 silc_asn1_free(asn1);
689 silc_sfree(stack, identifier);
690 silc_sfree(stack, pk);
691 silc_sfree(stack, key);
692 silc_buffer_sfree(stack, buf);
694 silc_asn1_free(asn1);
698 /* Return key length */
700 SILC_PKCS_PUBLIC_KEY_BITLEN(silc_pkcs_silc_public_key_bitlen)
702 SilcSILCPublicKey silc_pubkey = public_key;
703 return silc_pubkey->pkcs->public_key_bitlen(silc_pubkey->pkcs,
704 silc_pubkey->public_key);
707 /* Copy public key */
709 SILC_PKCS_PUBLIC_KEY_COPY(silc_pkcs_silc_public_key_copy)
711 SilcSILCPublicKey silc_pubkey = public_key, new_pubkey;
712 SilcPublicKeyIdentifier ident = &silc_pubkey->identifier;
714 new_pubkey = silc_calloc(1, sizeof(*new_pubkey));
717 new_pubkey->pkcs = silc_pubkey->pkcs;
719 new_pubkey->public_key =
720 silc_pubkey->pkcs->public_key_copy(silc_pubkey->pkcs,
721 silc_pubkey->public_key);
722 if (!new_pubkey->public_key) {
723 silc_free(new_pubkey);
728 new_pubkey->identifier.username =
729 silc_memdup(ident->username, strlen(ident->username));
731 new_pubkey->identifier.host =
732 silc_memdup(ident->host, strlen(ident->host));
734 new_pubkey->identifier.realname =
735 silc_memdup(ident->realname, strlen(ident->realname));
737 new_pubkey->identifier.email =
738 silc_memdup(ident->email, strlen(ident->email));
740 new_pubkey->identifier.org =
741 silc_memdup(ident->org, strlen(ident->org));
743 new_pubkey->identifier.country =
744 silc_memdup(ident->country, strlen(ident->country));
746 new_pubkey->identifier.version =
747 silc_memdup(ident->version, strlen(ident->version));
752 /* Compares public keys */
754 SILC_PKCS_PUBLIC_KEY_COMPARE(silc_pkcs_silc_public_key_compare)
756 SilcSILCPublicKey k1 = key1, k2 = key2;
758 if (strcmp(k1->pkcs->name, k2->pkcs->name))
761 if ((k1->identifier.username && !k2->identifier.username) ||
762 (!k1->identifier.username && k2->identifier.username) ||
763 (k1->identifier.username && k2->identifier.username &&
764 strcmp(k1->identifier.username, k2->identifier.username)))
767 if ((k1->identifier.host && !k2->identifier.host) ||
768 (!k1->identifier.host && k2->identifier.host) ||
769 (k1->identifier.host && k2->identifier.host &&
770 strcmp(k1->identifier.host, k2->identifier.host)))
773 if ((k1->identifier.realname && !k2->identifier.realname) ||
774 (!k1->identifier.realname && k2->identifier.realname) ||
775 (k1->identifier.realname && k2->identifier.realname &&
776 strcmp(k1->identifier.realname, k2->identifier.realname)))
779 if ((k1->identifier.email && !k2->identifier.email) ||
780 (!k1->identifier.email && k2->identifier.email) ||
781 (k1->identifier.email && k2->identifier.email &&
782 strcmp(k1->identifier.email, k2->identifier.email)))
785 if ((k1->identifier.org && !k2->identifier.org) ||
786 (!k1->identifier.org && k2->identifier.org) ||
787 (k1->identifier.org && k2->identifier.org &&
788 strcmp(k1->identifier.org, k2->identifier.org)))
791 if ((k1->identifier.country && !k2->identifier.country) ||
792 (!k1->identifier.country && k2->identifier.country) ||
793 (k1->identifier.country && k2->identifier.country &&
794 strcmp(k1->identifier.country, k2->identifier.country)))
797 if ((k1->identifier.version && !k2->identifier.version) ||
798 (!k1->identifier.version && k2->identifier.version) ||
799 (k1->identifier.version && k2->identifier.version &&
800 strcmp(k1->identifier.version, k2->identifier.version)))
803 return k1->pkcs->public_key_compare(k1->pkcs, k1->public_key, k2->public_key);
806 /* Frees public key */
808 SILC_PKCS_PUBLIC_KEY_FREE(silc_pkcs_silc_public_key_free)
810 SilcSILCPublicKey silc_pubkey = public_key;
812 silc_pubkey->pkcs->public_key_free(silc_pubkey->pkcs,
813 silc_pubkey->public_key);
815 silc_free(silc_pubkey->identifier.username);
816 silc_free(silc_pubkey->identifier.host);
817 silc_free(silc_pubkey->identifier.realname);
818 silc_free(silc_pubkey->identifier.email);
819 silc_free(silc_pubkey->identifier.org);
820 silc_free(silc_pubkey->identifier.country);
821 silc_free(silc_pubkey->identifier.version);
822 silc_free(silc_pubkey);
826 /*************************** Private key routines ****************************/
828 /* Private key file magic */
829 #define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
831 /* Imports SILC implementation style private key file */
833 SILC_PKCS_IMPORT_PRIVATE_KEY_FILE(silc_pkcs_silc_import_private_key_file)
839 unsigned char tmp[32], keymat[64], *data = NULL;
840 SilcUInt32 i, len, magic, mac_len;
843 SILC_LOG_DEBUG(("Parsing SILC private key file"));
845 /* Check start of file and remove header from the data. */
846 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
847 if (filedata_len < len + strlen(SILC_PKCS_PRIVATE_KEYFILE_END)) {
848 SILC_LOG_DEBUG(("Malformed SILC private key header"));
851 for (i = 0; i < len; i++) {
852 if (*filedata != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
853 SILC_LOG_DEBUG(("Malformed SILC private key header"));
859 len = filedata_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
860 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
863 case SILC_PKCS_FILE_BIN:
866 case SILC_PKCS_FILE_BASE64:
867 data = silc_base64_decode(NULL, filedata, filedata_len, &len);
874 memset(tmp, 0, sizeof(tmp));
875 memset(keymat, 0, sizeof(keymat));
877 /* Check file magic */
878 SILC_GET32_MSB(magic, filedata);
879 if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
880 SILC_LOG_DEBUG(("Private key does not have correct magic"));
884 /* Allocate the AES cipher */
885 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
886 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
889 blocklen = silc_cipher_get_block_len(aes);
890 if (blocklen * 2 > sizeof(tmp)) {
891 silc_cipher_free(aes);
895 /* Allocate SHA1 hash */
896 if (!silc_hash_alloc("sha1", &sha1)) {
897 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
898 silc_cipher_free(aes);
903 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
904 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
905 silc_hash_free(sha1);
906 silc_cipher_free(aes);
910 /* Derive the decryption key from the provided key material. The key
911 is 256 bits length, and derived by taking hash of the data, then
912 re-hashing the data and the previous digest, and using the first and
913 second digest as the key. */
914 silc_hash_init(sha1);
915 silc_hash_update(sha1, passphrase, passphrase_len);
916 silc_hash_final(sha1, keymat);
917 silc_hash_init(sha1);
918 silc_hash_update(sha1, passphrase, passphrase_len);
919 silc_hash_update(sha1, keymat, 16);
920 silc_hash_final(sha1, keymat + 16);
922 /* Set the key to the cipher */
923 silc_cipher_set_key(aes, keymat, 256, FALSE);
925 /* First, verify the MAC of the private key data */
926 mac_len = silc_hmac_len(sha1hmac);
927 silc_hmac_init_with_key(sha1hmac, keymat, 16);
928 silc_hmac_update(sha1hmac, filedata, len - mac_len);
929 silc_hmac_final(sha1hmac, tmp, NULL);
930 if (memcmp(tmp, filedata + (len - mac_len), mac_len)) {
931 SILC_LOG_DEBUG(("Integrity check for private key failed"));
932 memset(keymat, 0, sizeof(keymat));
933 memset(tmp, 0, sizeof(tmp));
934 silc_hmac_free(sha1hmac);
935 silc_hash_free(sha1);
936 silc_cipher_free(aes);
942 /* Decrypt the private key buffer */
943 silc_cipher_decrypt(aes, filedata, filedata, len - mac_len, NULL);
944 SILC_GET32_MSB(i, filedata);
946 SILC_LOG_DEBUG(("Bad private key length in buffer!"));
947 memset(keymat, 0, sizeof(keymat));
948 memset(tmp, 0, sizeof(tmp));
949 silc_hmac_free(sha1hmac);
950 silc_hash_free(sha1);
951 silc_cipher_free(aes);
958 memset(keymat, 0, sizeof(keymat));
959 memset(tmp, 0, sizeof(tmp));
960 silc_hmac_free(sha1hmac);
961 silc_hash_free(sha1);
962 silc_cipher_free(aes);
964 /* Import the private key */
965 ret = silc_pkcs_silc_import_private_key(pkcs, NULL, filedata,
966 len, ret_private_key, ret_alg);
970 return ret ? TRUE : FALSE;
973 /* Private key version */
974 #define SILC_PRIVATE_KEY_VERSION_1 0x82171273
975 #define SILC_PRIVATE_KEY_VERSION_2 0xf911a3d1
977 /* Imports SILC implementation style private key */
979 SILC_PKCS_IMPORT_PRIVATE_KEY(silc_pkcs_silc_import_private_key)
981 SilcBufferStruct buf;
982 SilcBufferStruct alg_key;
983 SilcSILCPrivateKey silc_privkey = NULL;
984 SilcAsn1 asn1 = NULL;
986 SilcUInt32 keydata_len;
987 unsigned char *pkcs_name = NULL, *key_data;
990 SILC_LOG_DEBUG(("Parsing SILC private key"));
992 if (!ret_private_key)
995 silc_buffer_set(&buf, (unsigned char *)key, key_len);
997 /* Get algorithm name and identifier */
999 silc_buffer_unformat(&buf,
1000 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
1003 SILC_LOG_DEBUG(("Cannot decode private key buffer"));
1007 if (pkcs_len < 1 || pkcs_len > silc_buffer_truelen(&buf)) {
1008 SILC_LOG_DEBUG(("Malformed private key buffer"));
1012 /* Get key data. We assume that rest of the buffer is key data. */
1013 silc_buffer_pull(&buf, 2 + pkcs_len);
1014 keydata_len = silc_buffer_len(&buf);
1015 ret = silc_buffer_unformat(&buf,
1016 SILC_STR_UI_XNSTRING(&key_data, keydata_len),
1021 /* Allocate SILC private key context */
1022 silc_privkey = silc_calloc(1, sizeof(*silc_privkey));
1026 asn1 = silc_asn1_alloc(NULL);
1030 if (!strcmp(pkcs_name, "rsa")) {
1031 /* Parse the RSA SILC private key */
1033 SilcMPInt n, e, d, dp, dq, qp, p, q;
1035 SilcUInt32 len, ver;
1037 if (keydata_len < 4)
1039 silc_buffer_set(&k, key_data, keydata_len);
1041 /* Get version. Key without the version is old style private key
1042 and we need to do some computation to get it to correct format. */
1043 if (silc_buffer_unformat(&k,
1044 SILC_STR_UI_INT(&ver),
1047 silc_buffer_pull(&k, 4);
1049 if (ver != SILC_PRIVATE_KEY_VERSION_1 &&
1050 ver != SILC_PRIVATE_KEY_VERSION_2) {
1054 if (silc_buffer_unformat(&k,
1055 SILC_STR_UI_INT(&len),
1058 silc_buffer_pull(&k, 4);
1061 /* Get PKCS object. Different PKCS #1 scheme is used with different
1063 if (ver == 0 || ver == SILC_PRIVATE_KEY_VERSION_1) {
1064 /* Version 0 and 1 */
1065 alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid");
1067 /* Version 2 and newer */
1068 alg = silc_pkcs_find_algorithm(pkcs_name, "pkcs1");
1071 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1074 silc_privkey->pkcs = alg;
1076 SILC_LOG_DEBUG(("Private key version %s",
1077 (ver == SILC_PRIVATE_KEY_VERSION_1 ? "1" :
1078 ver == SILC_PRIVATE_KEY_VERSION_2 ? "2" : "0")));
1081 if (silc_buffer_unformat(&k,
1082 SILC_STR_DATA(&tmp, len),
1086 silc_mp_bin2mp(tmp, len, &e);
1087 silc_buffer_pull(&k, len);
1090 if (silc_buffer_unformat(&k,
1091 SILC_STR_UI_INT(&len),
1094 silc_buffer_pull(&k, 4);
1095 if (silc_buffer_unformat(&k,
1096 SILC_STR_DATA(&tmp, len),
1100 silc_mp_bin2mp(tmp, len, &n);
1101 silc_buffer_pull(&k, len);
1104 if (silc_buffer_unformat(&k,
1105 SILC_STR_UI_INT(&len),
1108 silc_buffer_pull(&k, 4);
1109 if (silc_buffer_unformat(&k,
1110 SILC_STR_DATA(&tmp, len),
1114 silc_mp_bin2mp(tmp, len, &d);
1115 silc_buffer_pull(&k, len);
1118 if (silc_buffer_unformat(&k,
1119 SILC_STR_UI_INT(&len),
1122 silc_buffer_pull(&k, 4);
1123 if (silc_buffer_unformat(&k,
1124 SILC_STR_DATA(&tmp, len),
1128 silc_mp_bin2mp(tmp, len, &dp);
1129 silc_buffer_pull(&k, len);
1132 if (silc_buffer_unformat(&k,
1133 SILC_STR_UI_INT(&len),
1136 silc_buffer_pull(&k, 4);
1137 if (silc_buffer_unformat(&k,
1138 SILC_STR_DATA(&tmp, len),
1142 silc_mp_bin2mp(tmp, len, &dq);
1143 silc_buffer_pull(&k, len);
1149 if (silc_buffer_unformat(&k,
1150 SILC_STR_UI_INT(&len),
1153 silc_buffer_pull(&k, 4);
1154 if (silc_buffer_len(&k) < len)
1156 silc_buffer_pull(&k, len);
1159 if (silc_buffer_unformat(&k,
1160 SILC_STR_UI_INT(&len),
1163 silc_buffer_pull(&k, 4);
1164 if (silc_buffer_len(&k) < len)
1166 silc_buffer_pull(&k, len);
1171 if (silc_buffer_unformat(&k,
1172 SILC_STR_UI_INT(&len),
1175 silc_buffer_pull(&k, 4);
1176 if (silc_buffer_unformat(&k,
1177 SILC_STR_DATA(&tmp, len),
1181 silc_mp_bin2mp(tmp, len, &qp);
1182 silc_buffer_pull(&k, len);
1186 if (silc_buffer_unformat(&k,
1187 SILC_STR_UI_INT(&len),
1190 silc_buffer_pull(&k, 4);
1191 if (silc_buffer_unformat(&k,
1192 SILC_STR_DATA(&tmp, len),
1196 silc_mp_bin2mp(tmp, len, &p);
1197 silc_buffer_pull(&k, len);
1200 if (silc_buffer_unformat(&k,
1201 SILC_STR_UI_INT(&len),
1204 silc_buffer_pull(&k, 4);
1205 if (silc_buffer_unformat(&k,
1206 SILC_STR_DATA(&tmp, len),
1210 silc_mp_bin2mp(tmp, len, &q);
1211 silc_buffer_pull(&k, len);
1214 /* Old version. Compute to new version */
1215 SILC_LOG_DEBUG(("Old version private key"));
1217 silc_mp_modinv(&qp, &q, &p);
1220 /* Encode to PKCS #1 format */
1221 memset(&alg_key, 0, sizeof(alg_key));
1222 if (!silc_asn1_encode(asn1, &alg_key,
1224 SILC_ASN1_SHORT_INT(0),
1233 SILC_ASN1_END, SILC_ASN1_END))
1242 silc_mp_uninit(&dp);
1243 silc_mp_uninit(&dq);
1244 silc_mp_uninit(&qp);
1246 } else if (!strcmp(pkcs_name, "dsa")) {
1247 SILC_NOT_IMPLEMENTED("DSA SILC Private Key");
1251 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1255 /* Import PKCS algorithm private key */
1256 if (!alg->import_private_key(alg, alg_key.data, silc_buffer_len(&alg_key),
1257 &silc_privkey->private_key))
1260 silc_free(pkcs_name);
1261 silc_asn1_free(asn1);
1263 *ret_private_key = silc_privkey;
1269 silc_free(pkcs_name);
1270 silc_free(silc_privkey);
1272 silc_asn1_free(asn1);
1273 SILC_LOG_ERROR(("Malformed SILC private key "));
1277 /* Exports private key as SILC implementation style private key file */
1279 SILC_PKCS_EXPORT_PRIVATE_KEY_FILE(silc_pkcs_silc_export_private_key_file)
1284 SilcBuffer buf, enc;
1285 SilcUInt32 len, blocklen, padlen, key_len;
1286 unsigned char *key, *data;
1287 unsigned char tmp[32], keymat[64];
1290 SILC_LOG_DEBUG(("Encoding SILC private key file"));
1292 /* Export the private key */
1293 key = silc_pkcs_silc_export_private_key(pkcs, stack, private_key, &key_len);
1297 memset(tmp, 0, sizeof(tmp));
1298 memset(keymat, 0, sizeof(keymat));
1300 /* Allocate the AES cipher */
1301 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1302 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1303 silc_sfree(stack, key);
1306 blocklen = silc_cipher_get_block_len(aes);
1307 if (blocklen * 2 > sizeof(tmp)) {
1308 silc_cipher_free(aes);
1309 silc_sfree(stack, key);
1313 /* Allocate SHA1 hash */
1314 if (!silc_hash_alloc("sha1", &sha1)) {
1315 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1316 silc_sfree(stack, key);
1317 silc_cipher_free(aes);
1322 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1323 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1324 silc_sfree(stack, key);
1325 silc_hash_free(sha1);
1326 silc_cipher_free(aes);
1330 /* Derive the encryption key from the provided key material. The key
1331 is 256 bits length, and derived by taking hash of the data, then
1332 re-hashing the data and the previous digest, and using the first and
1333 second digest as the key. */
1334 silc_hash_init(sha1);
1335 silc_hash_update(sha1, passphrase, passphrase_len);
1336 silc_hash_final(sha1, keymat);
1337 silc_hash_init(sha1);
1338 silc_hash_update(sha1, passphrase, passphrase_len);
1339 silc_hash_update(sha1, keymat, 16);
1340 silc_hash_final(sha1, keymat + 16);
1342 /* Set the key to the cipher */
1343 silc_cipher_set_key(aes, keymat, 256, TRUE);
1345 /* Encode the buffer to be encrypted. Add padding to it too, at least
1346 block size of the cipher. */
1348 /* Allocate buffer for encryption */
1349 len = silc_hmac_len(sha1hmac);
1350 padlen = 16 + (16 - ((key_len + 4) % blocklen));
1351 enc = silc_buffer_salloc_size(stack, 4 + 4 + key_len + padlen + len);
1353 silc_sfree(stack, key);
1354 silc_hmac_free(sha1hmac);
1355 silc_hash_free(sha1);
1356 silc_cipher_free(aes);
1360 /* Generate padding */
1361 for (i = 0; i < padlen; i++)
1362 tmp[i] = silc_rng_get_byte_fast(rng);
1364 /* Put magic number */
1365 SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
1366 silc_buffer_pull(enc, 4);
1368 /* Encode the buffer */
1369 silc_buffer_sformat(stack, enc,
1370 SILC_STR_UI_INT(key_len),
1371 SILC_STR_UI_XNSTRING(key, key_len),
1372 SILC_STR_UI_XNSTRING(tmp, padlen),
1374 silc_sfree(stack, key);
1377 silc_cipher_encrypt(aes, enc->data, enc->data, silc_buffer_len(enc) - len,
1378 silc_cipher_get_iv(aes));
1380 silc_buffer_push(enc, 4);
1382 /* Compute HMAC over the encrypted data and append the MAC to data.
1383 The key is the first digest of the original key material. */
1384 key_len = silc_buffer_len(enc) - len;
1385 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1386 silc_hmac_update(sha1hmac, enc->data, key_len);
1387 silc_buffer_pull(enc, key_len);
1388 silc_hmac_final(sha1hmac, enc->data, NULL);
1389 silc_buffer_push(enc, key_len);
1392 memset(keymat, 0, sizeof(keymat));
1393 memset(tmp, 0, sizeof(tmp));
1394 silc_hmac_free(sha1hmac);
1395 silc_hash_free(sha1);
1396 silc_cipher_free(aes);
1399 case SILC_PKCS_FILE_BIN:
1402 case SILC_PKCS_FILE_BASE64:
1403 data = silc_base64_encode_file(stack, enc->data, silc_buffer_len(enc));
1405 silc_buffer_clear(enc);
1406 silc_buffer_sfree(stack, enc);
1409 silc_sfree(stack, silc_buffer_steal(enc, NULL));
1410 silc_buffer_set(enc, data, strlen(data));
1415 key_len = silc_buffer_len(enc);
1417 /* Encode the data and save to file */
1418 len = key_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1419 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1420 buf = silc_buffer_salloc_size(stack, len);
1422 silc_buffer_sfree(stack, enc);
1425 silc_buffer_sformat(stack, buf,
1426 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
1427 SILC_STR_UI_XNSTRING(key, key_len),
1428 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
1431 silc_buffer_sfree(stack, enc);
1432 data = silc_buffer_steal(buf, ret_len);
1433 silc_buffer_sfree(stack, buf);
1438 /* Exports private key as SILC implementation style private key */
1440 SILC_PKCS_EXPORT_PRIVATE_KEY(silc_pkcs_silc_export_private_key)
1442 SilcSILCPrivateKey silc_privkey = private_key;
1443 const SilcPKCSAlgorithm *alg = silc_privkey->pkcs;
1444 SilcBufferStruct alg_key;
1445 SilcBuffer buf = NULL;
1446 SilcAsn1 asn1 = NULL;
1447 unsigned char *prv = NULL, *key = NULL, *ret;
1448 SilcUInt32 prv_len, key_len, totlen;
1450 SILC_LOG_DEBUG(("Encoding SILC private key"));
1452 /* Export PKCS algorithm private key */
1453 if (alg->export_private_key)
1454 prv = alg->export_private_key(alg, stack,
1455 silc_privkey->private_key, &prv_len);
1458 silc_buffer_set(&alg_key, prv, prv_len);
1460 asn1 = silc_asn1_alloc(stack);
1464 if (!strcmp(alg->name, "rsa")) {
1465 /* Parse the PKCS #1 private key */
1466 SilcMPInt n, e, d, dp, dq, qp, p, q;
1467 SilcUInt32 e_len, n_len, d_len, dp_len, dq_len,
1468 qp_len, p_len, q_len, len = 0;
1469 unsigned char *nb, *eb, *db, *dpb, *dqb, *qpb, *pb, *qb;
1471 if (!silc_asn1_decode(asn1, &alg_key,
1473 SILC_ASN1_INT(NULL),
1482 SILC_ASN1_END, SILC_ASN1_END))
1485 /* Encode to SILC RSA private key */
1486 eb = silc_mp_mp2bin(&e, 0, &e_len);
1487 nb = silc_mp_mp2bin(&n, 0, &n_len);
1488 db = silc_mp_mp2bin(&d, 0, &d_len);
1489 dpb = silc_mp_mp2bin(&dp, 0, &dp_len);
1490 dqb = silc_mp_mp2bin(&dq, 0, &dq_len);
1491 qpb = silc_mp_mp2bin(&qp, 0, &qp_len);
1492 pb = silc_mp_mp2bin(&p, 0, &p_len);
1493 qb = silc_mp_mp2bin(&q, 0, &q_len);
1494 len = 4 + e_len + 4 + n_len + 4 + d_len + 4+ dp_len + 4 +
1495 dq_len + 4 + qp_len + 4 + p_len + 4 + q_len + 4;
1497 buf = silc_buffer_salloc_size(stack, len);
1500 if (silc_buffer_sformat(stack, buf,
1501 SILC_STR_UI_INT(SILC_PRIVATE_KEY_VERSION_1),
1502 SILC_STR_UI_INT(e_len),
1503 SILC_STR_UI_XNSTRING(eb, e_len),
1504 SILC_STR_UI_INT(n_len),
1505 SILC_STR_UI_XNSTRING(nb, n_len),
1506 SILC_STR_UI_INT(d_len),
1507 SILC_STR_UI_XNSTRING(db, d_len),
1508 SILC_STR_UI_INT(dp_len),
1509 SILC_STR_UI_XNSTRING(dpb, dp_len),
1510 SILC_STR_UI_INT(dq_len),
1511 SILC_STR_UI_XNSTRING(dqb, dq_len),
1512 SILC_STR_UI_INT(qp_len),
1513 SILC_STR_UI_XNSTRING(qpb, qp_len),
1514 SILC_STR_UI_INT(p_len),
1515 SILC_STR_UI_XNSTRING(pb, p_len),
1516 SILC_STR_UI_INT(q_len),
1517 SILC_STR_UI_XNSTRING(qb, q_len),
1521 key = silc_buffer_steal(buf, &key_len);
1522 silc_buffer_sfree(stack, buf);
1532 } else if (!strcmp(alg->name, "dsa")) {
1533 SILC_NOT_IMPLEMENTED("SILC DSA Private Key");
1537 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1541 /* Encode SILC private key */
1542 totlen = 2 + strlen(alg->name) + key_len;
1543 buf = silc_buffer_salloc_size(stack, totlen);
1546 if (silc_buffer_sformat(stack, buf,
1547 SILC_STR_UI_SHORT(strlen(alg->name)),
1548 SILC_STR_UI32_STRING(alg->name),
1549 SILC_STR_UI_XNSTRING(key, key_len),
1553 ret = silc_buffer_steal(buf, ret_len);
1554 silc_buffer_sfree(stack, buf);
1555 silc_sfree(stack, prv);
1556 silc_sfree(stack, key);
1557 silc_asn1_free(asn1);
1562 silc_sfree(stack, prv);
1563 silc_sfree(stack, key);
1564 silc_buffer_sfree(stack, buf);
1568 /* Return key length */
1570 SILC_PKCS_PRIVATE_KEY_BITLEN(silc_pkcs_silc_private_key_bitlen)
1572 SilcSILCPrivateKey silc_privkey = private_key;
1573 return silc_privkey->pkcs->private_key_bitlen(silc_privkey->pkcs,
1574 silc_privkey->private_key);
1577 /* Frees private key */
1579 SILC_PKCS_PRIVATE_KEY_FREE(silc_pkcs_silc_private_key_free)
1581 SilcSILCPrivateKey silc_privkey = private_key;
1583 silc_privkey->pkcs->private_key_free(silc_privkey->pkcs,
1584 silc_privkey->private_key);
1585 silc_free(silc_privkey);
1589 /***************************** PKCS operations ******************************/
1591 /* Encrypts as specified in SILC protocol specification */
1593 SILC_PKCS_ENCRYPT(silc_pkcs_silc_encrypt)
1595 SilcSILCPublicKey silc_pubkey = public_key;
1597 if (!silc_pubkey->pkcs->encrypt) {
1598 encrypt_cb(FALSE, NULL, 0, context);
1602 return silc_pubkey->pkcs->encrypt(silc_pubkey->pkcs,
1603 silc_pubkey->public_key,
1604 src, src_len, rng, encrypt_cb, context);
1607 /* Decrypts as specified in SILC protocol specification */
1609 SILC_PKCS_DECRYPT(silc_pkcs_silc_decrypt)
1611 SilcSILCPrivateKey silc_privkey = private_key;
1613 if (!silc_privkey->pkcs->decrypt) {
1614 decrypt_cb(FALSE, NULL, 0, context);
1618 return silc_privkey->pkcs->decrypt(silc_privkey->pkcs,
1619 silc_privkey->private_key,
1620 src, src_len, decrypt_cb, context);
1623 /* Signs as specified in SILC protocol specification */
1625 SILC_PKCS_SIGN(silc_pkcs_silc_sign)
1627 SilcSILCPrivateKey silc_privkey = private_key;
1629 if (!silc_privkey->pkcs->sign) {
1630 sign_cb(FALSE, NULL, 0, context);
1634 return silc_privkey->pkcs->sign(silc_privkey->pkcs,
1635 silc_privkey->private_key,
1637 compute_hash, hash, rng,
1641 /* Verifies as specified in SILC protocol specification */
1643 SILC_PKCS_VERIFY(silc_pkcs_silc_verify)
1645 SilcSILCPublicKey silc_pubkey = public_key;
1647 if (!silc_pubkey->pkcs->verify) {
1648 verify_cb(FALSE, context);
1652 return silc_pubkey->pkcs->verify(silc_pubkey->pkcs,
1653 silc_pubkey->public_key,
1654 signature, signature_len,
1655 data, data_len, hash, rng,
1656 verify_cb, context);