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)) {
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(filedata, filedata_len, &filedata_len);
347 SILC_LOG_ERROR(("Malformed SILC public key encoding"));
354 ret = silc_pkcs_silc_import_public_key(filedata, filedata_len,
358 return ret ? TRUE : FALSE;
361 /* Imports SILC protocol style public key */
363 int silc_pkcs_silc_import_public_key(unsigned char *key,
365 void **ret_public_key)
367 const SilcPKCSAlgorithm *pkcs;
368 SilcBufferStruct buf, alg_key;
369 SilcSILCPublicKey silc_pubkey = NULL;
370 SilcAsn1 asn1 = NULL;
371 SilcUInt32 totlen, keydata_len;
372 SilcUInt16 pkcs_len, identifier_len;
373 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
376 SILC_LOG_DEBUG(("Parsing SILC public key"));
381 silc_buffer_set(&buf, key, key_len);
384 ret = silc_buffer_unformat(&buf,
386 SILC_STR_UI_INT(&totlen),
391 /* Backwards compatibility */
392 if (totlen == key_len)
395 if (totlen + 4 != key_len)
398 /* Get algorithm name and identifier */
400 silc_buffer_unformat(&buf,
402 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
403 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
408 if (pkcs_len < 1 || identifier_len < 3 ||
409 pkcs_len + identifier_len > totlen)
413 keydata_len = silc_buffer_len(&buf);
414 ret = silc_buffer_unformat(&buf,
415 SILC_STR_DATA(&key_data, keydata_len),
420 /* Allocate SILC public key context */
421 silc_pubkey = silc_calloc(1, sizeof(*silc_pubkey));
425 /* Decode SILC identifier */
426 if (!silc_pkcs_silc_decode_identifier(ident, &silc_pubkey->identifier))
429 asn1 = silc_asn1_alloc();
433 SILC_LOG_DEBUG(("Public key version %s",
434 (!silc_pubkey->identifier.version ? "1" :
435 silc_pubkey->identifier.version)));
437 if (!strcmp(pkcs_name, "rsa")) {
438 /* Parse the SILC RSA public key */
439 SilcUInt32 e_len, n_len;
442 /* Get PKCS object. Different PKCS #1 scheme is used with different
444 if (!silc_pubkey->identifier.version ||
445 atoi(silc_pubkey->identifier.version) <= 1) {
447 pkcs = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid");
449 /* Version 2 and newer */
450 pkcs = silc_pkcs_find_algorithm(pkcs_name, "pkcs1");
453 SILC_LOG_DEBUG(("Unsupported PKCS algorithm: rsa"));
456 silc_pubkey->pkcs = pkcs;
460 SILC_GET32_MSB(e_len, key_data);
461 if (!e_len || e_len + 4 > keydata_len)
464 silc_mp_bin2mp(key_data + 4, e_len, &e);
465 if (keydata_len < 4 + e_len + 4) {
469 SILC_GET32_MSB(n_len, key_data + 4 + e_len);
470 if (!n_len || e_len + 4 + n_len + 4 > keydata_len) {
475 silc_mp_bin2mp(key_data + 4 + e_len + 4, n_len, &n);
477 /* Encode to PKCS #1 format */
478 memset(&alg_key, 0, sizeof(alg_key));
479 if (!silc_asn1_encode(asn1, &alg_key,
483 SILC_ASN1_END, SILC_ASN1_END)) {
492 } else if (!strcmp(pkcs_name, "dsa")) {
493 SILC_NOT_IMPLEMENTED("DSA SILC Public Key");
497 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
501 /* Import PKCS algorithm public key */
502 if (!pkcs->import_public_key(alg_key.data, silc_buffer_len(&alg_key),
503 &silc_pubkey->public_key))
506 silc_free(pkcs_name);
508 silc_asn1_free(asn1);
510 *ret_public_key = silc_pubkey;
515 silc_free(pkcs_name);
517 silc_free(silc_pubkey);
519 silc_asn1_free(asn1);
520 SILC_LOG_ERROR(("Malformed SILC public key"));
524 /* Exports public key as SILC protocol style public key file */
527 silc_pkcs_silc_export_public_key_file(void *public_key,
528 SilcPKCSFileEncoding encoding,
532 unsigned char *key, *data;
535 SILC_LOG_DEBUG(("Encoding SILC public key file"));
538 key = silc_pkcs_silc_export_public_key(public_key, &key_len);
543 case SILC_PKCS_FILE_BIN:
546 case SILC_PKCS_FILE_BASE64:
547 data = silc_base64_encode_file(key, key_len);
552 key_len = strlen(data);
556 /* Encode SILC public key file */
557 buf = silc_buffer_alloc_size(key_len +
558 (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
559 strlen(SILC_PKCS_PUBLIC_KEYFILE_END)));
565 if (silc_buffer_format(buf,
566 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
567 SILC_STR_UI_XNSTRING(key, key_len),
568 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
570 silc_buffer_free(buf);
576 key = silc_buffer_steal(buf, ret_len);
577 silc_buffer_free(buf);
582 /* Exports public key as SILC protocol style public key */
584 unsigned char *silc_pkcs_silc_export_public_key(void *public_key,
587 SilcSILCPublicKey silc_pubkey = public_key;
588 const SilcPKCSAlgorithm *pkcs = silc_pubkey->pkcs;
589 SilcBufferStruct alg_key;
590 SilcBuffer buf = NULL;
591 SilcAsn1 asn1 = NULL;
592 unsigned char *pk = NULL, *key = NULL, *ret;
593 SilcUInt32 pk_len, key_len, totlen;
596 SILC_LOG_DEBUG(("Encoding SILC public key"));
598 /* Export PKCS algorithm public key */
599 if (pkcs->export_public_key)
600 pk = pkcs->export_public_key(silc_pubkey->public_key, &pk_len);
603 silc_buffer_set(&alg_key, pk, pk_len);
605 /* Encode identifier */
607 silc_pkcs_silc_encode_identifier(silc_pubkey->identifier.username,
608 silc_pubkey->identifier.host,
609 silc_pubkey->identifier.realname,
610 silc_pubkey->identifier.email,
611 silc_pubkey->identifier.org,
612 silc_pubkey->identifier.country,
613 silc_pubkey->identifier.version);
617 asn1 = silc_asn1_alloc();
621 if (!strcmp(pkcs->name, "rsa")) {
622 /* Parse the PKCS #1 public key */
624 SilcUInt32 n_len, e_len;
625 unsigned char *nb, *eb;
627 memset(&n, 0, sizeof(n));
628 memset(&e, 0, sizeof(e));
629 if (!silc_asn1_decode(asn1, &alg_key,
633 SILC_ASN1_END, SILC_ASN1_END))
636 /* Encode to SILC RSA public key */
637 eb = silc_mp_mp2bin(&e, 0, &e_len);
640 nb = silc_mp_mp2bin(&n, 0, &n_len);
643 key_len = e_len + 4 + n_len + 4;
644 key = silc_calloc(key_len, sizeof(*key));
648 /* Put e length and e */
649 SILC_PUT32_MSB(e_len, key);
650 memcpy(key + 4, eb, e_len);
652 /* Put n length and n. */
653 SILC_PUT32_MSB(n_len, key + 4 + e_len);
654 memcpy(key + 4 + e_len + 4, nb, n_len);
659 } else if (!strcmp(pkcs->name, "dsa")) {
660 SILC_NOT_IMPLEMENTED("SILC DSA Public Key");
664 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
668 /* Encode SILC Public Key */
669 totlen = 2 + strlen(pkcs->name) + 2 + strlen(identifier) + key_len;
670 buf = silc_buffer_alloc_size(totlen + 4);
673 if (silc_buffer_format(buf,
674 SILC_STR_UI_INT(totlen),
675 SILC_STR_UI_SHORT(strlen(pkcs->name)),
676 SILC_STR_UI32_STRING(pkcs->name),
677 SILC_STR_UI_SHORT(strlen(identifier)),
678 SILC_STR_UI32_STRING(identifier),
679 SILC_STR_UI_XNSTRING(key, key_len),
683 ret = silc_buffer_steal(buf, ret_len);
684 silc_buffer_free(buf);
686 silc_free(identifier);
687 silc_buffer_purge(&alg_key);
688 silc_asn1_free(asn1);
693 silc_free(identifier);
697 silc_buffer_free(buf);
699 silc_asn1_free(asn1);
703 /* Return key length */
705 SilcUInt32 silc_pkcs_silc_public_key_bitlen(void *public_key)
707 SilcSILCPublicKey silc_pubkey = public_key;
708 return silc_pubkey->pkcs->public_key_bitlen(silc_pubkey->public_key);
711 /* Copy public key */
713 void *silc_pkcs_silc_public_key_copy(void *public_key)
715 SilcSILCPublicKey silc_pubkey = public_key, new_pubkey;
716 SilcPublicKeyIdentifier ident = &silc_pubkey->identifier;
718 new_pubkey = silc_calloc(1, sizeof(*new_pubkey));
721 new_pubkey->pkcs = silc_pubkey->pkcs;
723 new_pubkey->public_key =
724 silc_pubkey->pkcs->public_key_copy(silc_pubkey->public_key);
725 if (!new_pubkey->public_key) {
726 silc_free(new_pubkey);
731 new_pubkey->identifier.username =
732 silc_memdup(ident->username, strlen(ident->username));
734 new_pubkey->identifier.host =
735 silc_memdup(ident->host, strlen(ident->host));
737 new_pubkey->identifier.realname =
738 silc_memdup(ident->realname, strlen(ident->realname));
740 new_pubkey->identifier.email =
741 silc_memdup(ident->email, strlen(ident->email));
743 new_pubkey->identifier.org =
744 silc_memdup(ident->org, strlen(ident->org));
746 new_pubkey->identifier.country =
747 silc_memdup(ident->country, strlen(ident->country));
749 new_pubkey->identifier.version =
750 silc_memdup(ident->version, strlen(ident->version));
755 /* Compares public keys */
757 SilcBool silc_pkcs_silc_public_key_compare(void *key1, void *key2)
759 SilcSILCPublicKey k1 = key1, k2 = key2;
761 if (strcmp(k1->pkcs->name, k2->pkcs->name))
764 if ((k1->identifier.username && !k2->identifier.username) ||
765 (!k1->identifier.username && k2->identifier.username) ||
766 (k1->identifier.username && k2->identifier.username &&
767 strcmp(k1->identifier.username, k2->identifier.username)))
770 if ((k1->identifier.host && !k2->identifier.host) ||
771 (!k1->identifier.host && k2->identifier.host) ||
772 (k1->identifier.host && k2->identifier.host &&
773 strcmp(k1->identifier.host, k2->identifier.host)))
776 if ((k1->identifier.realname && !k2->identifier.realname) ||
777 (!k1->identifier.realname && k2->identifier.realname) ||
778 (k1->identifier.realname && k2->identifier.realname &&
779 strcmp(k1->identifier.realname, k2->identifier.realname)))
782 if ((k1->identifier.email && !k2->identifier.email) ||
783 (!k1->identifier.email && k2->identifier.email) ||
784 (k1->identifier.email && k2->identifier.email &&
785 strcmp(k1->identifier.email, k2->identifier.email)))
788 if ((k1->identifier.org && !k2->identifier.org) ||
789 (!k1->identifier.org && k2->identifier.org) ||
790 (k1->identifier.org && k2->identifier.org &&
791 strcmp(k1->identifier.org, k2->identifier.org)))
794 if ((k1->identifier.country && !k2->identifier.country) ||
795 (!k1->identifier.country && k2->identifier.country) ||
796 (k1->identifier.country && k2->identifier.country &&
797 strcmp(k1->identifier.country, k2->identifier.country)))
800 if ((k1->identifier.version && !k2->identifier.version) ||
801 (!k1->identifier.version && k2->identifier.version) ||
802 (k1->identifier.version && k2->identifier.version &&
803 strcmp(k1->identifier.version, k2->identifier.version)))
806 return k1->pkcs->public_key_compare(k1->public_key, k2->public_key);
809 /* Frees public key */
811 void silc_pkcs_silc_public_key_free(void *public_key)
813 SilcSILCPublicKey silc_pubkey = public_key;
815 silc_pubkey->pkcs->public_key_free(silc_pubkey->public_key);
817 silc_free(silc_pubkey->identifier.username);
818 silc_free(silc_pubkey->identifier.host);
819 silc_free(silc_pubkey->identifier.realname);
820 silc_free(silc_pubkey->identifier.email);
821 silc_free(silc_pubkey->identifier.org);
822 silc_free(silc_pubkey->identifier.country);
823 silc_free(silc_pubkey->identifier.version);
824 silc_free(silc_pubkey);
828 /*************************** Private key routines ****************************/
830 /* Private key file magic */
831 #define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
833 /* Imports SILC implementation style private key file */
835 SilcBool silc_pkcs_silc_import_private_key_file(unsigned char *filedata,
836 SilcUInt32 filedata_len,
837 const char *passphrase,
838 SilcUInt32 passphrase_len,
839 SilcPKCSFileEncoding encoding,
840 void **ret_private_key)
846 unsigned char tmp[32], keymat[64], *data = NULL;
847 SilcUInt32 i, len, magic, mac_len;
850 SILC_LOG_DEBUG(("Parsing SILC private key file"));
852 /* Check start of file and remove header from the data. */
853 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
854 if (filedata_len < len + strlen(SILC_PKCS_PRIVATE_KEYFILE_END)) {
855 SILC_LOG_ERROR(("Malformed SILC private key header"));
858 for (i = 0; i < len; i++) {
859 if (*filedata != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
860 SILC_LOG_ERROR(("Malformed SILC private key header"));
866 len = filedata_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
867 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
870 case SILC_PKCS_FILE_BIN:
873 case SILC_PKCS_FILE_BASE64:
874 data = silc_base64_decode(filedata, filedata_len, &len);
876 SILC_LOG_ERROR(("Malformed SILC private key encoding"));
883 memset(tmp, 0, sizeof(tmp));
884 memset(keymat, 0, sizeof(keymat));
886 /* Check file magic */
887 SILC_GET32_MSB(magic, filedata);
888 if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
889 SILC_LOG_DEBUG(("Private key does not have correct magic"));
893 /* Allocate the AES cipher */
894 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
895 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
898 blocklen = silc_cipher_get_block_len(aes);
899 if (blocklen * 2 > sizeof(tmp)) {
900 silc_cipher_free(aes);
904 /* Allocate SHA1 hash */
905 if (!silc_hash_alloc("sha1", &sha1)) {
906 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
907 silc_cipher_free(aes);
912 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
913 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
914 silc_hash_free(sha1);
915 silc_cipher_free(aes);
919 /* Derive the decryption key from the provided key material. The key
920 is 256 bits length, and derived by taking hash of the data, then
921 re-hashing the data and the previous digest, and using the first and
922 second digest as the key. */
923 silc_hash_init(sha1);
924 silc_hash_update(sha1, passphrase, passphrase_len);
925 silc_hash_final(sha1, keymat);
926 silc_hash_init(sha1);
927 silc_hash_update(sha1, passphrase, passphrase_len);
928 silc_hash_update(sha1, keymat, 16);
929 silc_hash_final(sha1, keymat + 16);
931 /* Set the key to the cipher */
932 silc_cipher_set_key(aes, keymat, 256, FALSE);
934 /* First, verify the MAC of the private key data */
935 mac_len = silc_hmac_len(sha1hmac);
936 silc_hmac_init_with_key(sha1hmac, keymat, 16);
937 silc_hmac_update(sha1hmac, filedata, len - mac_len);
938 silc_hmac_final(sha1hmac, tmp, NULL);
939 if (memcmp(tmp, filedata + (len - mac_len), mac_len)) {
940 SILC_LOG_DEBUG(("Integrity check for private key failed"));
941 memset(keymat, 0, sizeof(keymat));
942 memset(tmp, 0, sizeof(tmp));
943 silc_hmac_free(sha1hmac);
944 silc_hash_free(sha1);
945 silc_cipher_free(aes);
951 /* Decrypt the private key buffer */
952 silc_cipher_decrypt(aes, filedata, filedata, len - mac_len, NULL);
953 SILC_GET32_MSB(i, filedata);
955 SILC_LOG_DEBUG(("Bad private key length in buffer!"));
956 memset(keymat, 0, sizeof(keymat));
957 memset(tmp, 0, sizeof(tmp));
958 silc_hmac_free(sha1hmac);
959 silc_hash_free(sha1);
960 silc_cipher_free(aes);
967 memset(keymat, 0, sizeof(keymat));
968 memset(tmp, 0, sizeof(tmp));
969 silc_hmac_free(sha1hmac);
970 silc_hash_free(sha1);
971 silc_cipher_free(aes);
973 /* Import the private key */
974 ret = silc_pkcs_silc_import_private_key(filedata, len, ret_private_key);
978 return ret ? TRUE : FALSE;
981 /* Private key version */
982 #define SILC_PRIVATE_KEY_VERSION_1 0x82171273
983 #define SILC_PRIVATE_KEY_VERSION_2 0xf911a3d1
985 /* Imports SILC implementation style private key */
987 int silc_pkcs_silc_import_private_key(unsigned char *key,
989 void **ret_private_key)
991 SilcBufferStruct buf;
992 const SilcPKCSAlgorithm *pkcs;
993 SilcBufferStruct alg_key;
994 SilcSILCPrivateKey silc_privkey = NULL;
995 SilcAsn1 asn1 = NULL;
997 SilcUInt32 keydata_len;
998 unsigned char *pkcs_name = NULL, *key_data;
1001 SILC_LOG_DEBUG(("Parsing SILC private key"));
1003 if (!ret_private_key)
1006 silc_buffer_set(&buf, key, key_len);
1008 /* Get algorithm name and identifier */
1010 silc_buffer_unformat(&buf,
1011 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
1014 SILC_LOG_DEBUG(("Cannot decode private key buffer"));
1018 if (pkcs_len < 1 || pkcs_len > silc_buffer_truelen(&buf)) {
1019 SILC_LOG_DEBUG(("Malformed private key buffer"));
1023 /* Get key data. We assume that rest of the buffer is key data. */
1024 silc_buffer_pull(&buf, 2 + pkcs_len);
1025 keydata_len = silc_buffer_len(&buf);
1026 ret = silc_buffer_unformat(&buf,
1027 SILC_STR_UI_XNSTRING(&key_data, keydata_len),
1032 /* Allocate SILC private key context */
1033 silc_privkey = silc_calloc(1, sizeof(*silc_privkey));
1037 asn1 = silc_asn1_alloc();
1041 if (!strcmp(pkcs_name, "rsa")) {
1042 /* Parse the RSA SILC private key */
1044 SilcMPInt n, e, d, dp, dq, qp, p, q;
1046 SilcUInt32 len, ver;
1048 if (keydata_len < 4)
1050 silc_buffer_set(&k, key_data, keydata_len);
1052 /* Get version. Key without the version is old style private key
1053 and we need to do some computation to get it to correct format. */
1054 if (silc_buffer_unformat(&k,
1055 SILC_STR_UI_INT(&ver),
1058 silc_buffer_pull(&k, 4);
1060 if (ver != SILC_PRIVATE_KEY_VERSION_1 &&
1061 ver != SILC_PRIVATE_KEY_VERSION_2) {
1065 if (silc_buffer_unformat(&k,
1066 SILC_STR_UI_INT(&len),
1069 silc_buffer_pull(&k, 4);
1072 /* Get PKCS object. Different PKCS #1 scheme is used with different
1074 if (ver == 0 || ver == SILC_PRIVATE_KEY_VERSION_1) {
1075 /* Version 0 and 1 */
1076 pkcs = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid");
1078 /* Version 2 and newer */
1079 pkcs = silc_pkcs_find_algorithm(pkcs_name, "pkcs1");
1082 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1085 silc_privkey->pkcs = pkcs;
1087 SILC_LOG_DEBUG(("Private key version %s",
1088 (ver == SILC_PRIVATE_KEY_VERSION_1 ? "1" :
1089 ver == SILC_PRIVATE_KEY_VERSION_2 ? "2" : "0")));
1092 if (silc_buffer_unformat(&k,
1093 SILC_STR_DATA(&tmp, len),
1097 silc_mp_bin2mp(tmp, len, &e);
1098 silc_buffer_pull(&k, len);
1101 if (silc_buffer_unformat(&k,
1102 SILC_STR_UI_INT(&len),
1105 silc_buffer_pull(&k, 4);
1106 if (silc_buffer_unformat(&k,
1107 SILC_STR_DATA(&tmp, len),
1111 silc_mp_bin2mp(tmp, len, &n);
1112 silc_buffer_pull(&k, len);
1115 if (silc_buffer_unformat(&k,
1116 SILC_STR_UI_INT(&len),
1119 silc_buffer_pull(&k, 4);
1120 if (silc_buffer_unformat(&k,
1121 SILC_STR_DATA(&tmp, len),
1125 silc_mp_bin2mp(tmp, len, &d);
1126 silc_buffer_pull(&k, len);
1129 if (silc_buffer_unformat(&k,
1130 SILC_STR_UI_INT(&len),
1133 silc_buffer_pull(&k, 4);
1134 if (silc_buffer_unformat(&k,
1135 SILC_STR_DATA(&tmp, len),
1139 silc_mp_bin2mp(tmp, len, &dp);
1140 silc_buffer_pull(&k, len);
1143 if (silc_buffer_unformat(&k,
1144 SILC_STR_UI_INT(&len),
1147 silc_buffer_pull(&k, 4);
1148 if (silc_buffer_unformat(&k,
1149 SILC_STR_DATA(&tmp, len),
1153 silc_mp_bin2mp(tmp, len, &dq);
1154 silc_buffer_pull(&k, len);
1160 if (silc_buffer_unformat(&k,
1161 SILC_STR_UI_INT(&len),
1164 silc_buffer_pull(&k, 4);
1165 if (silc_buffer_len(&k) < len)
1167 silc_buffer_pull(&k, len);
1170 if (silc_buffer_unformat(&k,
1171 SILC_STR_UI_INT(&len),
1174 silc_buffer_pull(&k, 4);
1175 if (silc_buffer_len(&k) < len)
1177 silc_buffer_pull(&k, len);
1182 if (silc_buffer_unformat(&k,
1183 SILC_STR_UI_INT(&len),
1186 silc_buffer_pull(&k, 4);
1187 if (silc_buffer_unformat(&k,
1188 SILC_STR_DATA(&tmp, len),
1192 silc_mp_bin2mp(tmp, len, &qp);
1193 silc_buffer_pull(&k, len);
1197 if (silc_buffer_unformat(&k,
1198 SILC_STR_UI_INT(&len),
1201 silc_buffer_pull(&k, 4);
1202 if (silc_buffer_unformat(&k,
1203 SILC_STR_DATA(&tmp, len),
1207 silc_mp_bin2mp(tmp, len, &p);
1208 silc_buffer_pull(&k, len);
1211 if (silc_buffer_unformat(&k,
1212 SILC_STR_UI_INT(&len),
1215 silc_buffer_pull(&k, 4);
1216 if (silc_buffer_unformat(&k,
1217 SILC_STR_DATA(&tmp, len),
1221 silc_mp_bin2mp(tmp, len, &q);
1222 silc_buffer_pull(&k, len);
1225 /* Old version. Compute to new version */
1226 SILC_LOG_DEBUG(("Old version private key"));
1228 silc_mp_modinv(&qp, &q, &p);
1231 /* Encode to PKCS #1 format */
1232 memset(&alg_key, 0, sizeof(alg_key));
1233 if (!silc_asn1_encode(asn1, &alg_key,
1235 SILC_ASN1_SHORT_INT(0),
1244 SILC_ASN1_END, SILC_ASN1_END))
1253 silc_mp_uninit(&dp);
1254 silc_mp_uninit(&dq);
1255 silc_mp_uninit(&qp);
1257 } else if (!strcmp(pkcs_name, "dsa")) {
1258 SILC_NOT_IMPLEMENTED("DSA SILC Private Key");
1262 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1266 /* Import PKCS algorithm private key */
1267 if (!pkcs->import_private_key(alg_key.data, silc_buffer_len(&alg_key),
1268 &silc_privkey->private_key))
1271 silc_free(pkcs_name);
1272 silc_asn1_free(asn1);
1274 *ret_private_key = silc_privkey;
1279 silc_free(pkcs_name);
1280 silc_free(silc_privkey);
1282 silc_asn1_free(asn1);
1283 SILC_LOG_ERROR(("Malformed SILC private key "));
1287 /* Exports private key as SILC implementation style private key file */
1290 silc_pkcs_silc_export_private_key_file(void *private_key,
1291 const char *passphrase,
1292 SilcUInt32 passphrase_len,
1293 SilcPKCSFileEncoding encoding,
1295 SilcUInt32 *ret_len)
1300 SilcBuffer buf, enc;
1301 SilcUInt32 len, blocklen, padlen, key_len;
1302 unsigned char *key, *data;
1303 unsigned char tmp[32], keymat[64];
1306 SILC_LOG_DEBUG(("Encoding SILC private key file"));
1308 /* Export the private key */
1309 key = silc_pkcs_silc_export_private_key(private_key, &key_len);
1313 memset(tmp, 0, sizeof(tmp));
1314 memset(keymat, 0, sizeof(keymat));
1316 /* Allocate the AES cipher */
1317 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1318 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1322 blocklen = silc_cipher_get_block_len(aes);
1323 if (blocklen * 2 > sizeof(tmp)) {
1324 silc_cipher_free(aes);
1329 /* Allocate SHA1 hash */
1330 if (!silc_hash_alloc("sha1", &sha1)) {
1331 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1332 silc_cipher_free(aes);
1337 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1338 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1339 silc_hash_free(sha1);
1340 silc_cipher_free(aes);
1344 /* Derive the encryption key from the provided key material. The key
1345 is 256 bits length, and derived by taking hash of the data, then
1346 re-hashing the data and the previous digest, and using the first and
1347 second digest as the key. */
1348 silc_hash_init(sha1);
1349 silc_hash_update(sha1, passphrase, passphrase_len);
1350 silc_hash_final(sha1, keymat);
1351 silc_hash_init(sha1);
1352 silc_hash_update(sha1, passphrase, passphrase_len);
1353 silc_hash_update(sha1, keymat, 16);
1354 silc_hash_final(sha1, keymat + 16);
1356 /* Set the key to the cipher */
1357 silc_cipher_set_key(aes, keymat, 256, TRUE);
1359 /* Encode the buffer to be encrypted. Add padding to it too, at least
1360 block size of the cipher. */
1362 /* Allocate buffer for encryption */
1363 len = silc_hmac_len(sha1hmac);
1364 padlen = 16 + (16 - ((key_len + 4) % blocklen));
1365 enc = silc_buffer_alloc_size(4 + 4 + key_len + padlen + len);
1367 silc_hmac_free(sha1hmac);
1368 silc_hash_free(sha1);
1369 silc_cipher_free(aes);
1373 /* Generate padding */
1374 for (i = 0; i < padlen; i++)
1375 tmp[i] = silc_rng_get_byte_fast(rng);
1377 /* Put magic number */
1378 SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
1379 silc_buffer_pull(enc, 4);
1381 /* Encode the buffer */
1382 silc_buffer_format(enc,
1383 SILC_STR_UI_INT(key_len),
1384 SILC_STR_UI_XNSTRING(key, key_len),
1385 SILC_STR_UI_XNSTRING(tmp, padlen),
1390 silc_cipher_encrypt(aes, enc->data, enc->data, silc_buffer_len(enc) - len,
1391 silc_cipher_get_iv(aes));
1393 silc_buffer_push(enc, 4);
1395 /* Compute HMAC over the encrypted data and append the MAC to data.
1396 The key is the first digest of the original key material. */
1397 key_len = silc_buffer_len(enc) - len;
1398 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1399 silc_hmac_update(sha1hmac, enc->data, key_len);
1400 silc_buffer_pull(enc, key_len);
1401 silc_hmac_final(sha1hmac, enc->data, NULL);
1402 silc_buffer_push(enc, key_len);
1405 memset(keymat, 0, sizeof(keymat));
1406 memset(tmp, 0, sizeof(tmp));
1407 silc_hmac_free(sha1hmac);
1408 silc_hash_free(sha1);
1409 silc_cipher_free(aes);
1412 case SILC_PKCS_FILE_BIN:
1415 case SILC_PKCS_FILE_BASE64:
1416 data = silc_base64_encode_file(enc->data, silc_buffer_len(enc));
1418 silc_buffer_clear(enc);
1419 silc_buffer_free(enc);
1422 silc_free(silc_buffer_steal(enc, NULL));
1423 silc_buffer_set(enc, data, strlen(data));
1428 key_len = silc_buffer_len(enc);
1430 /* Encode the data and save to file */
1431 len = key_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1432 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1433 buf = silc_buffer_alloc_size(len);
1435 silc_buffer_free(enc);
1438 silc_buffer_format(buf,
1439 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
1440 SILC_STR_UI_XNSTRING(key, key_len),
1441 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
1444 silc_buffer_free(enc);
1445 data = silc_buffer_steal(buf, ret_len);
1446 silc_buffer_free(buf);
1451 /* Exports private key as SILC implementation style private key */
1453 unsigned char *silc_pkcs_silc_export_private_key(void *private_key,
1454 SilcUInt32 *ret_len)
1456 SilcSILCPrivateKey silc_privkey = private_key;
1457 const SilcPKCSAlgorithm *pkcs = silc_privkey->pkcs;
1458 SilcBufferStruct alg_key;
1459 SilcBuffer buf = NULL;
1460 SilcAsn1 asn1 = NULL;
1461 unsigned char *prv = NULL, *key = NULL, *ret;
1462 SilcUInt32 prv_len, key_len, totlen;
1464 SILC_LOG_DEBUG(("Encoding SILC private key"));
1466 /* Export PKCS algorithm private key */
1467 if (pkcs->export_private_key)
1468 prv = pkcs->export_private_key(silc_privkey->private_key, &prv_len);
1471 silc_buffer_set(&alg_key, prv, prv_len);
1473 asn1 = silc_asn1_alloc();
1477 if (!strcmp(pkcs->name, "rsa")) {
1478 /* Parse the PKCS #1 private key */
1479 SilcMPInt n, e, d, dp, dq, qp, p, q;
1480 SilcUInt32 e_len, n_len, d_len, dp_len, dq_len,
1481 qp_len, p_len, q_len, len = 0;
1482 unsigned char *nb, *eb, *db, *dpb, *dqb, *qpb, *pb, *qb;
1484 if (!silc_asn1_decode(asn1, &alg_key,
1486 SILC_ASN1_INT(NULL),
1495 SILC_ASN1_END, SILC_ASN1_END))
1498 /* Encode to SILC RSA private key */
1499 eb = silc_mp_mp2bin(&e, 0, &e_len);
1500 nb = silc_mp_mp2bin(&n, 0, &n_len);
1501 db = silc_mp_mp2bin(&d, 0, &d_len);
1502 dpb = silc_mp_mp2bin(&dp, 0, &dp_len);
1503 dqb = silc_mp_mp2bin(&dq, 0, &dq_len);
1504 qpb = silc_mp_mp2bin(&qp, 0, &qp_len);
1505 pb = silc_mp_mp2bin(&p, 0, &p_len);
1506 qb = silc_mp_mp2bin(&q, 0, &q_len);
1507 len = 4 + e_len + 4 + n_len + 4 + d_len + 4+ dp_len + 4 +
1508 dq_len + 4 + qp_len + 4 + p_len + 4 + q_len + 4;
1510 buf = silc_buffer_alloc_size(len);
1513 if (silc_buffer_format(buf,
1514 SILC_STR_UI_INT(SILC_PRIVATE_KEY_VERSION_1),
1515 SILC_STR_UI_INT(e_len),
1516 SILC_STR_UI_XNSTRING(eb, e_len),
1517 SILC_STR_UI_INT(n_len),
1518 SILC_STR_UI_XNSTRING(nb, n_len),
1519 SILC_STR_UI_INT(d_len),
1520 SILC_STR_UI_XNSTRING(db, d_len),
1521 SILC_STR_UI_INT(dp_len),
1522 SILC_STR_UI_XNSTRING(dpb, dp_len),
1523 SILC_STR_UI_INT(dq_len),
1524 SILC_STR_UI_XNSTRING(dqb, dq_len),
1525 SILC_STR_UI_INT(qp_len),
1526 SILC_STR_UI_XNSTRING(qpb, qp_len),
1527 SILC_STR_UI_INT(p_len),
1528 SILC_STR_UI_XNSTRING(pb, p_len),
1529 SILC_STR_UI_INT(q_len),
1530 SILC_STR_UI_XNSTRING(qb, q_len),
1534 key = silc_buffer_steal(buf, &key_len);
1535 silc_buffer_free(buf);
1545 } else if (!strcmp(pkcs->name, "dsa")) {
1546 SILC_NOT_IMPLEMENTED("SILC DSA Private Key");
1550 SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
1554 /* Encode SILC private key */
1555 totlen = 2 + strlen(pkcs->name) + key_len;
1556 buf = silc_buffer_alloc_size(totlen);
1559 if (silc_buffer_format(buf,
1560 SILC_STR_UI_SHORT(strlen(pkcs->name)),
1561 SILC_STR_UI32_STRING(pkcs->name),
1562 SILC_STR_UI_XNSTRING(key, key_len),
1566 ret = silc_buffer_steal(buf, ret_len);
1567 silc_buffer_free(buf);
1570 silc_asn1_free(asn1);
1578 silc_buffer_free(buf);
1582 /* Return key length */
1584 SilcUInt32 silc_pkcs_silc_private_key_bitlen(void *private_key)
1586 SilcSILCPrivateKey silc_privkey = private_key;
1587 return silc_privkey->pkcs->private_key_bitlen(silc_privkey->private_key);
1590 /* Frees private key */
1592 void silc_pkcs_silc_private_key_free(void *private_key)
1594 SilcSILCPrivateKey silc_privkey = private_key;
1596 silc_privkey->pkcs->private_key_free(silc_privkey->private_key);
1598 silc_free(silc_privkey);
1602 /***************************** PKCS operations ******************************/
1604 /* Encrypts as specified in SILC protocol specification */
1606 SilcBool silc_pkcs_silc_encrypt(void *public_key,
1610 SilcUInt32 dst_size,
1611 SilcUInt32 *ret_dst_len,
1614 SilcSILCPublicKey silc_pubkey = public_key;
1616 if (!silc_pubkey->pkcs->encrypt)
1619 return silc_pubkey->pkcs->encrypt(silc_pubkey->public_key,
1621 dst, dst_size, ret_dst_len, rng);
1624 /* Decrypts as specified in SILC protocol specification */
1626 SilcBool silc_pkcs_silc_decrypt(void *private_key,
1630 SilcUInt32 dst_size,
1631 SilcUInt32 *ret_dst_len)
1633 SilcSILCPrivateKey silc_privkey = private_key;
1635 if (!silc_privkey->pkcs->decrypt)
1638 return silc_privkey->pkcs->decrypt(silc_privkey->private_key,
1640 dst, dst_size, ret_dst_len);
1643 /* Signs as specified in SILC protocol specification */
1645 SilcBool silc_pkcs_silc_sign(void *private_key,
1648 unsigned char *signature,
1649 SilcUInt32 signature_size,
1650 SilcUInt32 *ret_signature_len,
1651 SilcBool compute_hash,
1654 SilcSILCPrivateKey silc_privkey = private_key;
1656 if (!silc_privkey->pkcs->sign)
1659 return silc_privkey->pkcs->sign(silc_privkey->private_key,
1661 signature, signature_size,
1662 ret_signature_len, compute_hash, hash);
1665 /* Verifies as specified in SILC protocol specification */
1667 SilcBool silc_pkcs_silc_verify(void *public_key,
1668 unsigned char *signature,
1669 SilcUInt32 signature_len,
1670 unsigned char *data,
1671 SilcUInt32 data_len,
1674 SilcSILCPublicKey silc_pubkey = public_key;
1676 if (!silc_pubkey->pkcs->verify)
1679 return silc_pubkey->pkcs->verify(silc_pubkey->public_key,
1680 signature, signature_len,
1681 data, data_len, hash);