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(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(char *username, char *host,
200 char *realname, char *email,
201 char *org, char *country,
204 SilcBufferStruct buf;
207 if (!username || !host)
209 if (strlen(username) < 3 || strlen(host) < 3)
212 memset(&buf, 0, sizeof(buf));
215 silc_buffer_format(&buf,
217 SILC_STR_UI32_STRING("UN="),
218 SILC_STR_UI32_STRING(username),
222 silc_buffer_format(&buf,
224 SILC_STR_UI32_STRING(", "),
225 SILC_STR_UI32_STRING("HN="),
226 SILC_STR_UI32_STRING(host),
230 silc_buffer_format(&buf,
232 SILC_STR_UI32_STRING(", "),
233 SILC_STR_UI32_STRING("RN="),
234 SILC_STR_UI32_STRING(realname),
238 silc_buffer_format(&buf,
240 SILC_STR_UI32_STRING(", "),
241 SILC_STR_UI32_STRING("E="),
242 SILC_STR_UI32_STRING(email),
246 silc_buffer_format(&buf,
248 SILC_STR_UI32_STRING(", "),
249 SILC_STR_UI32_STRING("O="),
250 SILC_STR_UI32_STRING(org),
254 silc_buffer_format(&buf,
256 SILC_STR_UI32_STRING(", "),
257 SILC_STR_UI32_STRING("C="),
258 SILC_STR_UI32_STRING(country),
262 if (strlen(version) > 1 || !isdigit(version[0])) {
263 silc_buffer_purge(&buf);
266 silc_buffer_format(&buf,
268 SILC_STR_UI32_STRING(", "),
269 SILC_STR_UI32_STRING("V="),
270 SILC_STR_UI32_STRING(version),
274 silc_buffer_format(&buf, SILC_STR_UI_CHAR(0), SILC_STR_END);
276 identifier = silc_buffer_steal(&buf, NULL);
280 /* Return SILC public key version */
282 int silc_pkcs_silc_public_key_version(SilcPublicKey public_key)
284 SilcSILCPublicKey silc_pubkey;
286 if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC)
289 silc_pubkey = public_key->public_key;
291 /* If version identifire is not present it is version 1. */
292 if (!silc_pubkey->identifier.version)
295 return atoi(silc_pubkey->identifier.version);
298 /*************************** Public key routines *****************************/
300 /* Returns PKCS algorithm context */
302 const SilcPKCSAlgorithm *silc_pkcs_silc_get_algorithm(void *public_key)
304 SilcSILCPublicKey silc_pubkey = public_key;
305 return silc_pubkey->pkcs;
308 /* Imports SILC protocol style public key from SILC public key file */
310 SilcBool silc_pkcs_silc_import_public_key_file(unsigned char *filedata,
311 SilcUInt32 filedata_len,
312 SilcPKCSFileEncoding encoding,
313 void **ret_public_key)
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))
328 for (i = 0; i < len; i++) {
329 if (*filedata != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i])
333 filedata_len -= (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
334 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
337 case SILC_PKCS_FILE_BIN:
340 case SILC_PKCS_FILE_BASE64:
341 data = silc_base64_decode(filedata, filedata_len, &filedata_len);
348 ret = silc_pkcs_silc_import_public_key(filedata, filedata_len,
352 return ret ? TRUE : FALSE;
355 /* Imports SILC protocol style public key */
357 int silc_pkcs_silc_import_public_key(unsigned char *key,
359 void **ret_public_key)
361 const SilcPKCSAlgorithm *pkcs;
362 SilcBufferStruct buf, alg_key;
363 SilcSILCPublicKey silc_pubkey = NULL;
364 SilcAsn1 asn1 = NULL;
365 SilcUInt32 totlen, keydata_len;
366 SilcUInt16 pkcs_len, identifier_len;
367 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
370 SILC_LOG_DEBUG(("Parsing SILC public key"));
375 silc_buffer_set(&buf, key, key_len);
378 ret = silc_buffer_unformat(&buf,
380 SILC_STR_UI_INT(&totlen),
385 /* Backwards compatibility */
386 if (totlen == key_len)
389 if (totlen + 4 != key_len)
392 /* Get algorithm name and identifier */
394 silc_buffer_unformat(&buf,
396 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
397 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
402 if (pkcs_len < 1 || identifier_len < 3 ||
403 pkcs_len + identifier_len > totlen)
407 keydata_len = silc_buffer_len(&buf);
408 ret = silc_buffer_unformat(&buf,
409 SILC_STR_DATA(&key_data, keydata_len),
414 /* Allocate SILC public key context */
415 silc_pubkey = silc_calloc(1, sizeof(*silc_pubkey));
419 /* Decode SILC identifier */
420 if (!silc_pkcs_silc_decode_identifier(ident, &silc_pubkey->identifier))
423 asn1 = silc_asn1_alloc();
427 SILC_LOG_DEBUG(("Public key version %s",
428 (!silc_pubkey->identifier.version ? " 1" :
429 silc_pubkey->identifier.version)));
431 if (!strcmp(pkcs_name, "rsa")) {
432 /* Parse the SILC RSA public key */
433 SilcUInt32 e_len, n_len;
436 /* Get PKCS object. Different PKCS #1 scheme is used with different
438 if (!silc_pubkey->identifier.version ||
439 atoi(silc_pubkey->identifier.version) <= 1) {
441 pkcs = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid");
443 /* Version 2 and newer */
444 pkcs = silc_pkcs_find_algorithm(pkcs_name, "pkcs1");
447 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
450 silc_pubkey->pkcs = pkcs;
454 SILC_GET32_MSB(e_len, key_data);
455 if (!e_len || e_len + 4 > keydata_len)
458 silc_mp_bin2mp(key_data + 4, e_len, &e);
459 if (keydata_len < 4 + e_len + 4) {
463 SILC_GET32_MSB(n_len, key_data + 4 + e_len);
464 if (!n_len || e_len + 4 + n_len + 4 > keydata_len) {
469 silc_mp_bin2mp(key_data + 4 + e_len + 4, n_len, &n);
471 /* Encode to PKCS #1 format */
472 memset(&alg_key, 0, sizeof(alg_key));
473 if (!silc_asn1_encode(asn1, &alg_key,
477 SILC_ASN1_END, SILC_ASN1_END)) {
486 } else if (!strcmp(pkcs_name, "dsa")) {
487 SILC_NOT_IMPLEMENTED("DSA SILC Public Key");
491 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
495 /* Import PKCS algorithm public key */
496 if (!pkcs->import_public_key(alg_key.data, silc_buffer_len(&alg_key),
497 &silc_pubkey->public_key))
500 silc_free(pkcs_name);
502 silc_asn1_free(asn1);
504 *ret_public_key = silc_pubkey;
509 silc_free(pkcs_name);
511 silc_free(silc_pubkey);
513 silc_asn1_free(asn1);
517 /* Exports public key as SILC protocol style public key file */
520 silc_pkcs_silc_export_public_key_file(void *public_key,
521 SilcPKCSFileEncoding encoding,
525 unsigned char *key, *data;
528 SILC_LOG_DEBUG(("Encoding SILC public key file"));
531 key = silc_pkcs_silc_export_public_key(public_key, &key_len);
536 case SILC_PKCS_FILE_BIN:
539 case SILC_PKCS_FILE_BASE64:
540 data = silc_base64_encode_file(key, key_len);
545 key_len = strlen(data);
549 /* Encode SILC public key file */
550 buf = silc_buffer_alloc_size(key_len +
551 (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
552 strlen(SILC_PKCS_PUBLIC_KEYFILE_END)));
558 if (silc_buffer_format(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_free(buf);
569 key = silc_buffer_steal(buf, ret_len);
570 silc_buffer_free(buf);
575 /* Exports public key as SILC protocol style public key */
577 unsigned char *silc_pkcs_silc_export_public_key(void *public_key,
580 SilcSILCPublicKey silc_pubkey = public_key;
581 const SilcPKCSAlgorithm *pkcs = silc_pubkey->pkcs;
582 SilcBufferStruct alg_key;
583 SilcBuffer buf = NULL;
584 SilcAsn1 asn1 = NULL;
585 unsigned char *pk = NULL, *key = NULL, *ret;
586 SilcUInt32 pk_len, key_len, totlen;
589 SILC_LOG_DEBUG(("Encoding SILC public key"));
591 /* Export PKCS algorithm public key */
592 if (pkcs->export_public_key)
593 pk = pkcs->export_public_key(silc_pubkey->public_key, &pk_len);
596 silc_buffer_set(&alg_key, pk, pk_len);
598 /* Encode identifier */
600 silc_pkcs_silc_encode_identifier(silc_pubkey->identifier.username,
601 silc_pubkey->identifier.host,
602 silc_pubkey->identifier.realname,
603 silc_pubkey->identifier.email,
604 silc_pubkey->identifier.org,
605 silc_pubkey->identifier.country,
606 silc_pubkey->identifier.version);
610 asn1 = silc_asn1_alloc();
614 if (!strcmp(pkcs->name, "rsa")) {
615 /* Parse the PKCS #1 public key */
617 SilcUInt32 n_len, e_len;
618 unsigned char *nb, *eb;
620 memset(&n, 0, sizeof(n));
621 memset(&e, 0, sizeof(e));
622 if (!silc_asn1_decode(asn1, &alg_key,
626 SILC_ASN1_END, SILC_ASN1_END))
629 /* Encode to SILC RSA public key */
630 eb = silc_mp_mp2bin(&e, 0, &e_len);
633 nb = silc_mp_mp2bin(&n, 0, &n_len);
636 key_len = e_len + 4 + n_len + 4;
637 key = silc_calloc(key_len, sizeof(*key));
641 /* Put e length and e */
642 SILC_PUT32_MSB(e_len, key);
643 memcpy(key + 4, eb, e_len);
645 /* Put n length and n. */
646 SILC_PUT32_MSB(n_len, key + 4 + e_len);
647 memcpy(key + 4 + e_len + 4, nb, n_len);
652 } else if (!strcmp(pkcs->name, "dsa")) {
653 SILC_NOT_IMPLEMENTED("SILC DSA Public Key");
657 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
661 /* Encode SILC Public Key */
662 totlen = 2 + strlen(pkcs->name) + 2 + strlen(identifier) + key_len;
663 buf = silc_buffer_alloc_size(totlen + 4);
666 if (silc_buffer_format(buf,
667 SILC_STR_UI_INT(totlen),
668 SILC_STR_UI_SHORT(strlen(pkcs->name)),
669 SILC_STR_UI32_STRING(pkcs->name),
670 SILC_STR_UI_SHORT(strlen(identifier)),
671 SILC_STR_UI32_STRING(identifier),
672 SILC_STR_UI_XNSTRING(key, key_len),
676 ret = silc_buffer_steal(buf, ret_len);
677 silc_buffer_free(buf);
679 silc_free(identifier);
680 silc_buffer_purge(&alg_key);
681 silc_asn1_free(asn1);
686 silc_free(identifier);
690 silc_buffer_free(buf);
692 silc_asn1_free(asn1);
696 /* Return key length */
698 SilcUInt32 silc_pkcs_silc_public_key_bitlen(void *public_key)
700 SilcSILCPublicKey silc_pubkey = public_key;
701 return silc_pubkey->pkcs->public_key_bitlen(silc_pubkey->public_key);
704 /* Copy public key */
706 void *silc_pkcs_silc_public_key_copy(void *public_key)
708 SilcSILCPublicKey silc_pubkey = public_key, new_pubkey;
710 new_pubkey = silc_calloc(1, sizeof(*new_pubkey));
713 new_pubkey->pkcs = silc_pubkey->pkcs;
715 new_pubkey->public_key =
716 silc_pubkey->pkcs->public_key_copy(silc_pubkey->public_key);
717 if (!new_pubkey->public_key) {
718 silc_free(new_pubkey);
725 /* Compares public keys */
727 SilcBool silc_pkcs_silc_public_key_compare(void *key1, void *key2)
729 SilcSILCPublicKey k1 = key1, k2 = key2;
731 if (strcmp(k1->pkcs->name, k2->pkcs->name))
734 if ((k1->identifier.username && !k2->identifier.username) ||
735 (!k1->identifier.username && k2->identifier.username) ||
736 (k1->identifier.username && k2->identifier.username &&
737 strcmp(k1->identifier.username, k2->identifier.username)))
740 if ((k1->identifier.host && !k2->identifier.host) ||
741 (!k1->identifier.host && k2->identifier.host) ||
742 (k1->identifier.host && k2->identifier.host &&
743 strcmp(k1->identifier.host, k2->identifier.host)))
746 if ((k1->identifier.realname && !k2->identifier.realname) ||
747 (!k1->identifier.realname && k2->identifier.realname) ||
748 (k1->identifier.realname && k2->identifier.realname &&
749 strcmp(k1->identifier.realname, k2->identifier.realname)))
752 if ((k1->identifier.email && !k2->identifier.email) ||
753 (!k1->identifier.email && k2->identifier.email) ||
754 (k1->identifier.email && k2->identifier.email &&
755 strcmp(k1->identifier.email, k2->identifier.email)))
758 if ((k1->identifier.org && !k2->identifier.org) ||
759 (!k1->identifier.org && k2->identifier.org) ||
760 (k1->identifier.org && k2->identifier.org &&
761 strcmp(k1->identifier.org, k2->identifier.org)))
764 if ((k1->identifier.country && !k2->identifier.country) ||
765 (!k1->identifier.country && k2->identifier.country) ||
766 (k1->identifier.country && k2->identifier.country &&
767 strcmp(k1->identifier.country, k2->identifier.country)))
770 if ((k1->identifier.version && !k2->identifier.version) ||
771 (!k1->identifier.version && k2->identifier.version) ||
772 (k1->identifier.version && k2->identifier.version &&
773 strcmp(k1->identifier.version, k2->identifier.version)))
776 return k1->pkcs->public_key_compare(k1->public_key, k2->public_key);
779 /* Frees public key */
781 void silc_pkcs_silc_public_key_free(void *public_key)
783 SilcSILCPublicKey silc_pubkey = public_key;
785 silc_pubkey->pkcs->public_key_free(silc_pubkey->public_key);
787 silc_free(silc_pubkey->identifier.username);
788 silc_free(silc_pubkey->identifier.host);
789 silc_free(silc_pubkey->identifier.realname);
790 silc_free(silc_pubkey->identifier.email);
791 silc_free(silc_pubkey->identifier.org);
792 silc_free(silc_pubkey->identifier.country);
793 silc_free(silc_pubkey->identifier.version);
794 silc_free(silc_pubkey);
798 /*************************** Private key routines ****************************/
800 /* Private key file magic */
801 #define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
803 /* Imports SILC implementation style private key file */
805 SilcBool silc_pkcs_silc_import_private_key_file(unsigned char *filedata,
806 SilcUInt32 filedata_len,
807 const char *passphrase,
808 SilcUInt32 passphrase_len,
809 SilcPKCSFileEncoding encoding,
810 void **ret_private_key)
816 unsigned char tmp[32], keymat[64], *data = NULL;
817 SilcUInt32 i, len, magic, mac_len;
820 SILC_LOG_DEBUG(("Parsing SILC private key file"));
822 /* Check start of file and remove header from the data. */
823 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
824 if (filedata_len < len + strlen(SILC_PKCS_PRIVATE_KEYFILE_END))
826 for (i = 0; i < len; i++) {
827 if (*filedata != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i])
832 len = filedata_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
833 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
836 case SILC_PKCS_FILE_BIN:
839 case SILC_PKCS_FILE_BASE64:
840 data = silc_base64_decode(filedata, filedata_len, &len);
847 memset(tmp, 0, sizeof(tmp));
848 memset(keymat, 0, sizeof(keymat));
850 /* Check file magic */
851 SILC_GET32_MSB(magic, filedata);
852 if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
853 SILC_LOG_DEBUG(("Private key does not have correct magic"));
857 /* Allocate the AES cipher */
858 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
859 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
862 blocklen = silc_cipher_get_block_len(aes);
863 if (blocklen * 2 > sizeof(tmp)) {
864 silc_cipher_free(aes);
868 /* Allocate SHA1 hash */
869 if (!silc_hash_alloc("sha1", &sha1)) {
870 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
871 silc_cipher_free(aes);
876 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
877 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
878 silc_hash_free(sha1);
879 silc_cipher_free(aes);
883 /* Derive the decryption key from the provided key material. The key
884 is 256 bits length, and derived by taking hash of the data, then
885 re-hashing the data and the previous digest, and using the first and
886 second digest as the key. */
887 silc_hash_init(sha1);
888 silc_hash_update(sha1, passphrase, passphrase_len);
889 silc_hash_final(sha1, keymat);
890 silc_hash_init(sha1);
891 silc_hash_update(sha1, passphrase, passphrase_len);
892 silc_hash_update(sha1, keymat, 16);
893 silc_hash_final(sha1, keymat + 16);
895 /* Set the key to the cipher */
896 silc_cipher_set_key(aes, keymat, 256, FALSE);
898 /* First, verify the MAC of the private key data */
899 mac_len = silc_hmac_len(sha1hmac);
900 silc_hmac_init_with_key(sha1hmac, keymat, 16);
901 silc_hmac_update(sha1hmac, filedata, len - mac_len);
902 silc_hmac_final(sha1hmac, tmp, NULL);
903 if (memcmp(tmp, filedata + (len - mac_len), mac_len)) {
904 SILC_LOG_DEBUG(("Integrity check for private key failed"));
905 memset(keymat, 0, sizeof(keymat));
906 memset(tmp, 0, sizeof(tmp));
907 silc_hmac_free(sha1hmac);
908 silc_hash_free(sha1);
909 silc_cipher_free(aes);
915 /* Decrypt the private key buffer */
916 silc_cipher_decrypt(aes, filedata, filedata, len - mac_len, NULL);
917 SILC_GET32_MSB(i, filedata);
919 SILC_LOG_DEBUG(("Bad private key length in buffer!"));
920 memset(keymat, 0, sizeof(keymat));
921 memset(tmp, 0, sizeof(tmp));
922 silc_hmac_free(sha1hmac);
923 silc_hash_free(sha1);
924 silc_cipher_free(aes);
931 memset(keymat, 0, sizeof(keymat));
932 memset(tmp, 0, sizeof(tmp));
933 silc_hmac_free(sha1hmac);
934 silc_hash_free(sha1);
935 silc_cipher_free(aes);
937 /* Import the private key */
938 ret = silc_pkcs_silc_import_private_key(filedata, len, ret_private_key);
942 return ret ? TRUE : FALSE;
945 /* Private key version */
946 #define SILC_PRIVATE_KEY_VERSION_1 0x82171273
947 #define SILC_PRIVATE_KEY_VERSION_2 0xf911a3d1
949 /* Imports SILC implementation style private key */
951 int silc_pkcs_silc_import_private_key(unsigned char *key,
953 void **ret_private_key)
955 SilcBufferStruct buf;
956 const SilcPKCSAlgorithm *pkcs;
957 SilcBufferStruct alg_key;
958 SilcSILCPrivateKey silc_privkey = NULL;
959 SilcAsn1 asn1 = NULL;
961 SilcUInt32 keydata_len;
962 unsigned char *pkcs_name = NULL, *key_data;
965 SILC_LOG_DEBUG(("Parsing SILC private key"));
967 if (!ret_private_key)
970 silc_buffer_set(&buf, key, key_len);
972 /* Get algorithm name and identifier */
974 silc_buffer_unformat(&buf,
975 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
978 SILC_LOG_DEBUG(("Cannot decode private key buffer"));
982 if (pkcs_len < 1 || pkcs_len > silc_buffer_truelen(&buf)) {
983 SILC_LOG_DEBUG(("Malformed private key buffer"));
987 /* Get key data. We assume that rest of the buffer is key data. */
988 silc_buffer_pull(&buf, 2 + pkcs_len);
989 keydata_len = silc_buffer_len(&buf);
990 ret = silc_buffer_unformat(&buf,
991 SILC_STR_UI_XNSTRING(&key_data, keydata_len),
996 /* Allocate SILC private key context */
997 silc_privkey = silc_calloc(1, sizeof(*silc_privkey));
1001 asn1 = silc_asn1_alloc();
1005 if (!strcmp(pkcs_name, "rsa")) {
1006 /* Parse the RSA SILC private key */
1008 SilcMPInt n, e, d, dp, dq, qp, p, q;
1010 SilcUInt32 len, ver;
1012 if (keydata_len < 4)
1014 silc_buffer_set(&k, key_data, keydata_len);
1016 /* Get version. Key without the version is old style private key
1017 and we need to do some computation to get it to correct format. */
1018 if (silc_buffer_unformat(&k,
1019 SILC_STR_UI_INT(&ver),
1022 silc_buffer_pull(&k, 4);
1024 if (ver != SILC_PRIVATE_KEY_VERSION_1 &&
1025 ver != SILC_PRIVATE_KEY_VERSION_2) {
1029 if (silc_buffer_unformat(&k,
1030 SILC_STR_UI_INT(&len),
1033 silc_buffer_pull(&k, 4);
1036 /* Get PKCS object. Different PKCS #1 scheme is used with different
1038 if (ver == 0 || ver == SILC_PRIVATE_KEY_VERSION_1) {
1039 /* Version 0 and 1 */
1040 pkcs = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid");
1042 /* Version 2 and newer */
1043 pkcs = silc_pkcs_find_algorithm(pkcs_name, "pkcs1");
1046 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1049 silc_privkey->pkcs = pkcs;
1051 SILC_LOG_DEBUG(("Private key version %s",
1052 (ver == SILC_PRIVATE_KEY_VERSION_1 ? "1" :
1053 ver == SILC_PRIVATE_KEY_VERSION_2 ? "2" : "0")));
1056 if (silc_buffer_unformat(&k,
1057 SILC_STR_DATA(&tmp, len),
1061 silc_mp_bin2mp(tmp, len, &e);
1062 silc_buffer_pull(&k, len);
1065 if (silc_buffer_unformat(&k,
1066 SILC_STR_UI_INT(&len),
1069 silc_buffer_pull(&k, 4);
1070 if (silc_buffer_unformat(&k,
1071 SILC_STR_DATA(&tmp, len),
1075 silc_mp_bin2mp(tmp, len, &n);
1076 silc_buffer_pull(&k, len);
1079 if (silc_buffer_unformat(&k,
1080 SILC_STR_UI_INT(&len),
1083 silc_buffer_pull(&k, 4);
1084 if (silc_buffer_unformat(&k,
1085 SILC_STR_DATA(&tmp, len),
1089 silc_mp_bin2mp(tmp, len, &d);
1090 silc_buffer_pull(&k, len);
1093 if (silc_buffer_unformat(&k,
1094 SILC_STR_UI_INT(&len),
1097 silc_buffer_pull(&k, 4);
1098 if (silc_buffer_unformat(&k,
1099 SILC_STR_DATA(&tmp, len),
1103 silc_mp_bin2mp(tmp, len, &dp);
1104 silc_buffer_pull(&k, len);
1107 if (silc_buffer_unformat(&k,
1108 SILC_STR_UI_INT(&len),
1111 silc_buffer_pull(&k, 4);
1112 if (silc_buffer_unformat(&k,
1113 SILC_STR_DATA(&tmp, len),
1117 silc_mp_bin2mp(tmp, len, &dq);
1118 silc_buffer_pull(&k, len);
1124 if (silc_buffer_unformat(&k,
1125 SILC_STR_UI_INT(&len),
1128 silc_buffer_pull(&k, 4);
1129 if (silc_buffer_len(&k) < len)
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_len(&k) < len)
1141 silc_buffer_pull(&k, len);
1146 if (silc_buffer_unformat(&k,
1147 SILC_STR_UI_INT(&len),
1150 silc_buffer_pull(&k, 4);
1151 if (silc_buffer_unformat(&k,
1152 SILC_STR_DATA(&tmp, len),
1156 silc_mp_bin2mp(tmp, len, &qp);
1157 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_unformat(&k,
1167 SILC_STR_DATA(&tmp, len),
1171 silc_mp_bin2mp(tmp, len, &p);
1172 silc_buffer_pull(&k, len);
1175 if (silc_buffer_unformat(&k,
1176 SILC_STR_UI_INT(&len),
1179 silc_buffer_pull(&k, 4);
1180 if (silc_buffer_unformat(&k,
1181 SILC_STR_DATA(&tmp, len),
1185 silc_mp_bin2mp(tmp, len, &q);
1186 silc_buffer_pull(&k, len);
1189 /* Old version. Compute to new version */
1190 SILC_LOG_DEBUG(("Old version private key"));
1192 silc_mp_modinv(&qp, &q, &p);
1195 /* Encode to PKCS #1 format */
1196 memset(&alg_key, 0, sizeof(alg_key));
1197 if (!silc_asn1_encode(asn1, &alg_key,
1199 SILC_ASN1_SHORT_INT(0),
1208 SILC_ASN1_END, SILC_ASN1_END))
1217 silc_mp_uninit(&dp);
1218 silc_mp_uninit(&dq);
1219 silc_mp_uninit(&qp);
1221 } else if (!strcmp(pkcs_name, "dsa")) {
1222 SILC_NOT_IMPLEMENTED("DSA SILC Private Key");
1226 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1230 /* Import PKCS algorithm private key */
1231 if (!pkcs->import_private_key(alg_key.data, silc_buffer_len(&alg_key),
1232 &silc_privkey->private_key))
1235 silc_free(pkcs_name);
1236 silc_asn1_free(asn1);
1238 *ret_private_key = silc_privkey;
1243 silc_free(pkcs_name);
1244 silc_free(silc_privkey);
1246 silc_asn1_free(asn1);
1250 /* Exports private key as SILC implementation style private key file */
1253 silc_pkcs_silc_export_private_key_file(void *private_key,
1254 const char *passphrase,
1255 SilcUInt32 passphrase_len,
1256 SilcPKCSFileEncoding encoding,
1258 SilcUInt32 *ret_len)
1263 SilcBuffer buf, enc;
1264 SilcUInt32 len, blocklen, padlen, key_len;
1265 unsigned char *key, *data;
1266 unsigned char tmp[32], keymat[64];
1269 SILC_LOG_DEBUG(("Encoding SILC private key file"));
1271 /* Export the private key */
1272 key = silc_pkcs_silc_export_private_key(private_key, &key_len);
1276 memset(tmp, 0, sizeof(tmp));
1277 memset(keymat, 0, sizeof(keymat));
1279 /* Allocate the AES cipher */
1280 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1281 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1285 blocklen = silc_cipher_get_block_len(aes);
1286 if (blocklen * 2 > sizeof(tmp)) {
1287 silc_cipher_free(aes);
1292 /* Allocate SHA1 hash */
1293 if (!silc_hash_alloc("sha1", &sha1)) {
1294 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1295 silc_cipher_free(aes);
1300 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1301 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1302 silc_hash_free(sha1);
1303 silc_cipher_free(aes);
1307 /* Derive the encryption key from the provided key material. The key
1308 is 256 bits length, and derived by taking hash of the data, then
1309 re-hashing the data and the previous digest, and using the first and
1310 second digest as the key. */
1311 silc_hash_init(sha1);
1312 silc_hash_update(sha1, passphrase, passphrase_len);
1313 silc_hash_final(sha1, keymat);
1314 silc_hash_init(sha1);
1315 silc_hash_update(sha1, passphrase, passphrase_len);
1316 silc_hash_update(sha1, keymat, 16);
1317 silc_hash_final(sha1, keymat + 16);
1319 /* Set the key to the cipher */
1320 silc_cipher_set_key(aes, keymat, 256, TRUE);
1322 /* Encode the buffer to be encrypted. Add padding to it too, at least
1323 block size of the cipher. */
1325 /* Allocate buffer for encryption */
1326 len = silc_hmac_len(sha1hmac);
1327 padlen = 16 + (16 - ((key_len + 4) % blocklen));
1328 enc = silc_buffer_alloc_size(4 + 4 + key_len + padlen + len);
1330 silc_hmac_free(sha1hmac);
1331 silc_hash_free(sha1);
1332 silc_cipher_free(aes);
1336 /* Generate padding */
1337 for (i = 0; i < padlen; i++)
1338 tmp[i] = silc_rng_get_byte_fast(rng);
1340 /* Put magic number */
1341 SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
1342 silc_buffer_pull(enc, 4);
1344 /* Encode the buffer */
1345 silc_buffer_format(enc,
1346 SILC_STR_UI_INT(key_len),
1347 SILC_STR_UI_XNSTRING(key, key_len),
1348 SILC_STR_UI_XNSTRING(tmp, padlen),
1353 silc_cipher_encrypt(aes, enc->data, enc->data, silc_buffer_len(enc) - len,
1354 silc_cipher_get_iv(aes));
1356 silc_buffer_push(enc, 4);
1358 /* Compute HMAC over the encrypted data and append the MAC to data.
1359 The key is the first digest of the original key material. */
1360 key_len = silc_buffer_len(enc) - len;
1361 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1362 silc_hmac_update(sha1hmac, enc->data, key_len);
1363 silc_buffer_pull(enc, key_len);
1364 silc_hmac_final(sha1hmac, enc->data, NULL);
1365 silc_buffer_push(enc, key_len);
1368 memset(keymat, 0, sizeof(keymat));
1369 memset(tmp, 0, sizeof(tmp));
1370 silc_hmac_free(sha1hmac);
1371 silc_hash_free(sha1);
1372 silc_cipher_free(aes);
1375 case SILC_PKCS_FILE_BIN:
1378 case SILC_PKCS_FILE_BASE64:
1379 data = silc_base64_encode_file(enc->data, silc_buffer_len(enc));
1381 silc_buffer_clear(enc);
1382 silc_buffer_free(enc);
1385 silc_free(silc_buffer_steal(enc, NULL));
1386 silc_buffer_set(enc, data, strlen(data));
1391 key_len = silc_buffer_len(enc);
1393 /* Encode the data and save to file */
1394 len = key_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1395 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1396 buf = silc_buffer_alloc_size(len);
1398 silc_buffer_free(enc);
1401 silc_buffer_format(buf,
1402 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
1403 SILC_STR_UI_XNSTRING(key, key_len),
1404 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
1407 silc_buffer_free(enc);
1408 data = silc_buffer_steal(buf, ret_len);
1409 silc_buffer_free(buf);
1414 /* Exports private key as SILC implementation style private key */
1416 unsigned char *silc_pkcs_silc_export_private_key(void *private_key,
1417 SilcUInt32 *ret_len)
1419 SilcSILCPrivateKey silc_privkey = private_key;
1420 const SilcPKCSAlgorithm *pkcs = silc_privkey->pkcs;
1421 SilcBufferStruct alg_key;
1422 SilcBuffer buf = NULL;
1423 SilcAsn1 asn1 = NULL;
1424 unsigned char *prv = NULL, *key = NULL, *ret;
1425 SilcUInt32 prv_len, key_len, totlen;
1427 SILC_LOG_DEBUG(("Encoding SILC private key"));
1429 /* Export PKCS algorithm private key */
1430 if (pkcs->export_private_key)
1431 prv = pkcs->export_private_key(silc_privkey->private_key, &prv_len);
1434 silc_buffer_set(&alg_key, prv, prv_len);
1436 asn1 = silc_asn1_alloc();
1440 if (!strcmp(pkcs->name, "rsa")) {
1441 /* Parse the PKCS #1 private key */
1442 SilcMPInt n, e, d, dp, dq, qp, p, q;
1443 SilcUInt32 e_len, n_len, d_len, dp_len, dq_len,
1444 qp_len, p_len, q_len, len = 0;
1445 unsigned char *nb, *eb, *db, *dpb, *dqb, *qpb, *pb, *qb;
1447 if (!silc_asn1_decode(asn1, &alg_key,
1449 SILC_ASN1_INT(NULL),
1458 SILC_ASN1_END, SILC_ASN1_END))
1461 /* Encode to SILC RSA private key */
1462 eb = silc_mp_mp2bin(&e, 0, &e_len);
1463 nb = silc_mp_mp2bin(&n, 0, &n_len);
1464 db = silc_mp_mp2bin(&d, 0, &d_len);
1465 dpb = silc_mp_mp2bin(&dp, 0, &dp_len);
1466 dqb = silc_mp_mp2bin(&dq, 0, &dq_len);
1467 qpb = silc_mp_mp2bin(&qp, 0, &qp_len);
1468 pb = silc_mp_mp2bin(&p, 0, &p_len);
1469 qb = silc_mp_mp2bin(&q, 0, &q_len);
1470 len = 4 + e_len + 4 + n_len + 4 + d_len + 4+ dp_len + 4 +
1471 dq_len + 4 + qp_len + 4 + p_len + 4 + q_len + 4;
1473 buf = silc_buffer_alloc_size(len);
1476 if (silc_buffer_format(buf,
1477 SILC_STR_UI_INT(SILC_PRIVATE_KEY_VERSION_1),
1478 SILC_STR_UI_INT(e_len),
1479 SILC_STR_UI_XNSTRING(eb, e_len),
1480 SILC_STR_UI_INT(n_len),
1481 SILC_STR_UI_XNSTRING(nb, n_len),
1482 SILC_STR_UI_INT(d_len),
1483 SILC_STR_UI_XNSTRING(db, d_len),
1484 SILC_STR_UI_INT(dp_len),
1485 SILC_STR_UI_XNSTRING(dpb, dp_len),
1486 SILC_STR_UI_INT(dq_len),
1487 SILC_STR_UI_XNSTRING(dqb, dq_len),
1488 SILC_STR_UI_INT(qp_len),
1489 SILC_STR_UI_XNSTRING(qpb, qp_len),
1490 SILC_STR_UI_INT(p_len),
1491 SILC_STR_UI_XNSTRING(pb, p_len),
1492 SILC_STR_UI_INT(q_len),
1493 SILC_STR_UI_XNSTRING(qb, q_len),
1497 key = silc_buffer_steal(buf, &key_len);
1498 silc_buffer_free(buf);
1508 } else if (!strcmp(pkcs->name, "dsa")) {
1509 SILC_NOT_IMPLEMENTED("SILC DSA Private Key");
1513 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1517 /* Encode SILC private key */
1518 totlen = 2 + strlen(pkcs->name) + key_len;
1519 buf = silc_buffer_alloc_size(totlen);
1522 if (silc_buffer_format(buf,
1523 SILC_STR_UI_SHORT(strlen(pkcs->name)),
1524 SILC_STR_UI32_STRING(pkcs->name),
1525 SILC_STR_UI_XNSTRING(key, key_len),
1529 ret = silc_buffer_steal(buf, ret_len);
1530 silc_buffer_free(buf);
1533 silc_asn1_free(asn1);
1541 silc_buffer_free(buf);
1545 /* Return key length */
1547 SilcUInt32 silc_pkcs_silc_private_key_bitlen(void *private_key)
1549 SilcSILCPrivateKey silc_privkey = private_key;
1550 return silc_privkey->pkcs->private_key_bitlen(silc_privkey->private_key);
1553 /* Frees private key */
1555 void silc_pkcs_silc_private_key_free(void *private_key)
1557 SilcSILCPrivateKey silc_privkey = private_key;
1559 silc_privkey->pkcs->private_key_free(silc_privkey->private_key);
1561 silc_free(silc_privkey);
1565 /***************************** PKCS operations ******************************/
1567 /* Encrypts as specified in SILC protocol specification */
1569 SilcBool silc_pkcs_silc_encrypt(void *public_key,
1573 SilcUInt32 dst_size,
1574 SilcUInt32 *ret_dst_len,
1577 SilcSILCPublicKey silc_pubkey = public_key;
1579 if (!silc_pubkey->pkcs->encrypt)
1582 return silc_pubkey->pkcs->encrypt(silc_pubkey->public_key,
1584 dst, dst_size, ret_dst_len, rng);
1587 /* Decrypts as specified in SILC protocol specification */
1589 SilcBool silc_pkcs_silc_decrypt(void *private_key,
1593 SilcUInt32 dst_size,
1594 SilcUInt32 *ret_dst_len)
1596 SilcSILCPrivateKey silc_privkey = private_key;
1598 if (!silc_privkey->pkcs->decrypt)
1601 return silc_privkey->pkcs->decrypt(silc_privkey->private_key,
1603 dst, dst_size, ret_dst_len);
1606 /* Signs as specified in SILC protocol specification */
1608 SilcBool silc_pkcs_silc_sign(void *private_key,
1611 unsigned char *signature,
1612 SilcUInt32 signature_size,
1613 SilcUInt32 *ret_signature_len,
1614 SilcBool compute_hash,
1617 SilcSILCPrivateKey silc_privkey = private_key;
1619 if (!silc_privkey->pkcs->sign)
1622 return silc_privkey->pkcs->sign(silc_privkey->private_key,
1624 signature, signature_size,
1625 ret_signature_len, compute_hash, hash);
1628 /* Verifies as specified in SILC protocol specification */
1630 SilcBool silc_pkcs_silc_verify(void *public_key,
1631 unsigned char *signature,
1632 SilcUInt32 signature_len,
1633 unsigned char *data,
1634 SilcUInt32 data_len,
1637 SilcSILCPublicKey silc_pubkey = public_key;
1639 if (!silc_pubkey->pkcs->verify)
1642 return silc_pubkey->pkcs->verify(silc_pubkey->public_key,
1643 signature, signature_len,
1644 data, data_len, hash);