5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 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.
21 #include "silcincludes.h"
25 /* The main SILC PKCS structure. */
26 struct SilcPKCSStruct {
27 void *context; /* Algorithm internal context */
28 SilcPKCSObject *pkcs; /* Algorithm implementation */
29 SilcUInt32 key_len; /* Key length in bits */
33 /* Dynamically registered list of PKCS. */
34 SilcDList silc_pkcs_list = NULL;
35 #define SILC_PKCS_LIST silc_pkcs_list
37 #define SILC_PKCS_LIST TRUE
38 #endif /* SILC_EPOC */
40 /* Static list of PKCS for silc_pkcs_register_default(). */
41 const SilcPKCSObject silc_default_pkcs[] =
43 /* RSA with PKCS #1 (Uses directly routines from Raw RSA operations) */
45 silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
46 silc_rsa_get_private_key, silc_rsa_set_public_key,
47 silc_rsa_set_private_key, silc_rsa_context_len,
48 silc_pkcs1_encrypt, silc_pkcs1_decrypt,
49 silc_pkcs1_sign, silc_pkcs1_verify },
51 /* Raw RSA operations */
53 silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
54 silc_rsa_get_private_key, silc_rsa_set_public_key,
55 silc_rsa_set_private_key, silc_rsa_context_len,
56 silc_rsa_encrypt, silc_rsa_decrypt,
57 silc_rsa_sign, silc_rsa_verify },
59 { NULL, NULL, NULL, NULL, NULL,
60 NULL, NULL, NULL, NULL, NULL, NULL }
63 /* Register a new PKCS into SILC. This is used at the initialization of
66 bool silc_pkcs_register(const SilcPKCSObject *pkcs)
71 SILC_LOG_DEBUG(("Registering new PKCS `%s'", pkcs->name));
73 /* Check if exists already */
75 SilcPKCSObject *entry;
76 silc_dlist_start(silc_pkcs_list);
77 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
78 if (!strcmp(entry->name, pkcs->name))
83 new = silc_calloc(1, sizeof(*new));
84 new->name = strdup(pkcs->name);
85 new->init = pkcs->init;
86 new->clear_keys = pkcs->clear_keys;
87 new->get_public_key = pkcs->get_public_key;
88 new->get_private_key = pkcs->get_private_key;
89 new->set_public_key = pkcs->set_public_key;
90 new->set_private_key = pkcs->set_private_key;
91 new->context_len = pkcs->context_len;
92 new->encrypt = pkcs->encrypt;
93 new->decrypt = pkcs->decrypt;
94 new->sign = pkcs->sign;
95 new->verify = pkcs->verify;
98 if (silc_pkcs_list == NULL)
99 silc_pkcs_list = silc_dlist_init();
100 silc_dlist_add(silc_pkcs_list, new);
102 #endif /* SILC_EPOC */
106 /* Unregister a PKCS from the SILC. */
108 bool silc_pkcs_unregister(SilcPKCSObject *pkcs)
111 SilcPKCSObject *entry;
113 SILC_LOG_DEBUG(("Unregistering PKCS"));
118 silc_dlist_start(silc_pkcs_list);
119 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
120 if (pkcs == SILC_ALL_PKCS || entry == pkcs) {
121 silc_dlist_del(silc_pkcs_list, entry);
122 silc_free(entry->name);
125 if (silc_dlist_count(silc_pkcs_list) == 0) {
126 silc_dlist_uninit(silc_pkcs_list);
127 silc_pkcs_list = NULL;
134 #endif /* SILC_EPOC */
138 /* Function that registers all the default PKCS (all builtin PKCS).
139 The application may use this to register the default PKCS if specific
140 PKCS in any specific order is not wanted. */
142 bool silc_pkcs_register_default(void)
147 for (i = 0; silc_default_pkcs[i].name; i++)
148 silc_pkcs_register(&(silc_default_pkcs[i]));
150 #endif /* SILC_EPOC */
154 bool silc_pkcs_unregister_all(void)
157 SilcPKCSObject *entry;
162 silc_dlist_start(silc_pkcs_list);
163 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
164 silc_pkcs_unregister(entry);
168 #endif /* SILC_EPOC */
172 /* Allocates a new SilcPKCS object. The new allocated object is returned
173 to the 'new_pkcs' argument. */
175 bool silc_pkcs_alloc(const unsigned char *name, SilcPKCS *new_pkcs)
177 SilcPKCSObject *entry = NULL;
179 SILC_LOG_DEBUG(("Allocating new PKCS object"));
182 if (silc_pkcs_list) {
183 silc_dlist_start(silc_pkcs_list);
184 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
185 if (!strcmp(entry->name, name))
191 /* On EPOC which don't have globals we check our constant hash list. */
193 for (i = 0; silc_default_pkcs[i].name; i++) {
194 if (!strcmp(silc_default_pkcs[i].name, name)) {
195 entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
200 #endif /* SILC_EPOC */
203 *new_pkcs = silc_calloc(1, sizeof(**new_pkcs));
204 (*new_pkcs)->pkcs = entry;
205 (*new_pkcs)->context = silc_calloc(1, entry->context_len());
212 /* Free's the PKCS object */
214 void silc_pkcs_free(SilcPKCS pkcs)
217 pkcs->pkcs->clear_keys(pkcs->context);
218 silc_free(pkcs->context);
223 /* Return TRUE if PKCS algorithm `name' is supported. */
225 bool silc_pkcs_is_supported(const unsigned char *name)
228 SilcPKCSObject *entry;
230 if (silc_pkcs_list) {
231 silc_dlist_start(silc_pkcs_list);
232 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
233 if (!strcmp(entry->name, name))
240 for (i = 0; silc_default_pkcs[i].name; i++)
241 if (!strcmp(silc_default_pkcs[i].name, name))
244 #endif /* SILC_EPOC */
248 /* Returns comma separated list of supported PKCS algorithms */
250 char *silc_pkcs_get_supported(void)
252 SilcPKCSObject *entry;
257 if (silc_pkcs_list) {
258 silc_dlist_start(silc_pkcs_list);
259 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
260 len += strlen(entry->name);
261 list = silc_realloc(list, len + 1);
263 memcpy(list + (len - strlen(entry->name)),
264 entry->name, strlen(entry->name));
265 memcpy(list + len, ",", 1);
272 for (i = 0; silc_default_pkcs[i].name; i++) {
273 entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
274 len += strlen(entry->name);
275 list = silc_realloc(list, len + 1);
277 memcpy(list + (len - strlen(entry->name)),
278 entry->name, strlen(entry->name));
279 memcpy(list + len, ",", 1);
283 #endif /* SILC_EPOC */
290 /* Generate new key pair into the `pkcs' context. */
292 bool silc_pkcs_generate_key(SilcPKCS pkcs, SilcUInt32 bits_key_len,
295 bool ret = pkcs->pkcs->init(pkcs->context, bits_key_len, rng);
297 pkcs->key_len = bits_key_len;
301 /* Returns the length of the key */
303 SilcUInt32 silc_pkcs_get_key_len(SilcPKCS pkcs)
305 return pkcs->key_len;
308 const char *silc_pkcs_get_name(SilcPKCS pkcs)
310 return pkcs->pkcs->name;
313 /* Returns SILC style public key */
315 unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, SilcUInt32 *len)
317 return pkcs->pkcs->get_public_key(pkcs->context, len);
320 /* Returns SILC style private key */
322 unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, SilcUInt32 *len)
324 return pkcs->pkcs->get_private_key(pkcs->context, len);
327 /* Sets public key from SilcPublicKey. */
329 SilcUInt32 silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
331 pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
333 return pkcs->key_len;
336 /* Sets public key from data. */
338 SilcUInt32 silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
341 pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, pk, pk_len);
342 return pkcs->key_len;
345 /* Sets private key from SilcPrivateKey. */
347 SilcUInt32 silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
350 key_len = pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
351 private_key->prv_len);
353 pkcs->key_len = key_len;
354 return pkcs->key_len;
357 /* Sets private key from data. */
359 SilcUInt32 silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
363 key_len = pkcs->pkcs->set_private_key(pkcs->context, prv, prv_len);
365 pkcs->key_len = key_len;
366 return pkcs->key_len;
371 bool silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
372 unsigned char *dst, SilcUInt32 *dst_len)
374 return pkcs->pkcs->encrypt(pkcs->context, src, src_len, dst, dst_len);
379 bool silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
380 unsigned char *dst, SilcUInt32 *dst_len)
382 return pkcs->pkcs->decrypt(pkcs->context, src, src_len, dst, dst_len);
385 /* Generates signature */
387 bool silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
388 unsigned char *dst, SilcUInt32 *dst_len)
390 return pkcs->pkcs->sign(pkcs->context, src, src_len, dst, dst_len);
393 /* Verifies signature */
395 bool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
396 SilcUInt32 signature_len, unsigned char *data,
399 return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
403 /* Generates signature with hash. The hash is signed. */
405 bool silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
406 unsigned char *src, SilcUInt32 src_len,
407 unsigned char *dst, SilcUInt32 *dst_len)
409 unsigned char hashr[SILC_HASH_MAXLEN];
413 silc_hash_make(hash, src, src_len, hashr);
414 hash_len = silc_hash_len(hash);
416 SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
418 ret = pkcs->pkcs->sign(pkcs->context, hashr, hash_len, dst, dst_len);
419 memset(hashr, 0, sizeof(hashr));
424 /* Verifies signature with hash. The `data' is hashed and verified against
427 bool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
428 unsigned char *signature,
429 SilcUInt32 signature_len,
433 unsigned char hashr[SILC_HASH_MAXLEN];
437 silc_hash_make(hash, data, data_len, hashr);
438 hash_len = silc_hash_len(hash);
440 SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
442 ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
444 memset(hashr, 0, sizeof(hashr));
449 /* Encodes and returns SILC public key identifier. If some of the
450 arguments is NULL those are not encoded into the identifier string.
451 Protocol says that at least username and host must be provided. */
453 char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
454 char *email, char *org, char *country)
458 SilcUInt32 len, tlen = 0;
460 if (!username || !host)
463 len = (username ? strlen(username) : 0) +
464 (host ? strlen(host) : 0) +
465 (realname ? strlen(realname) : 0) +
466 (email ? strlen(email) : 0) +
467 (org ? strlen(org) : 0) +
468 (country ? strlen(country) : 0);
473 len += 3 + 5 + 5 + 4 + 4 + 4;
474 buf = silc_buffer_alloc(len);
475 silc_buffer_pull_tail(buf, len);
478 silc_buffer_format(buf,
479 SILC_STR_UI32_STRING("UN="),
480 SILC_STR_UI32_STRING(username),
482 silc_buffer_pull(buf, 3 + strlen(username));
483 tlen = 3 + strlen(username);
487 silc_buffer_format(buf,
488 SILC_STR_UI32_STRING(", "),
489 SILC_STR_UI32_STRING("HN="),
490 SILC_STR_UI32_STRING(host),
492 silc_buffer_pull(buf, 5 + strlen(host));
493 tlen += 5 + strlen(host);
497 silc_buffer_format(buf,
498 SILC_STR_UI32_STRING(", "),
499 SILC_STR_UI32_STRING("RN="),
500 SILC_STR_UI32_STRING(realname),
502 silc_buffer_pull(buf, 5 + strlen(realname));
503 tlen += 5 + strlen(realname);
507 silc_buffer_format(buf,
508 SILC_STR_UI32_STRING(", "),
509 SILC_STR_UI32_STRING("E="),
510 SILC_STR_UI32_STRING(email),
512 silc_buffer_pull(buf, 4 + strlen(email));
513 tlen += 4 + strlen(email);
517 silc_buffer_format(buf,
518 SILC_STR_UI32_STRING(", "),
519 SILC_STR_UI32_STRING("O="),
520 SILC_STR_UI32_STRING(org),
522 silc_buffer_pull(buf, 4 + strlen(org));
523 tlen += 4 + strlen(org);
527 silc_buffer_format(buf,
528 SILC_STR_UI32_STRING(", "),
529 SILC_STR_UI32_STRING("C="),
530 SILC_STR_UI32_STRING(country),
532 silc_buffer_pull(buf, 4 + strlen(country));
533 tlen += 4 + strlen(country);
536 silc_buffer_push(buf, buf->data - buf->head);
537 identifier = silc_calloc(tlen + 1, sizeof(*identifier));
538 memcpy(identifier, buf->data, tlen);
539 silc_buffer_free(buf);
544 /* Decodes the provided `identifier' and returns allocated context for
547 SilcPublicKeyIdentifier silc_pkcs_decode_identifier(char *identifier)
549 SilcPublicKeyIdentifier ident;
553 ident = silc_calloc(1, sizeof(*ident));
557 len = strcspn(cp, ",");
562 if (len - 1 >= 0 && cp[len - 1] == '\\') {
564 if (len + 1 > strlen(cp)) {
569 len = strcspn(cp, ",") + len;
574 if (len - 1 >= 0 && cp[len - 1] != '\\')
582 item = silc_calloc(len + 1, sizeof(char));
583 if (len > strlen(cp))
585 memcpy(item, cp, len);
587 if (strstr(item, "UN="))
588 ident->username = strdup(item + strcspn(cp, "=") + 1);
589 else if (strstr(item, "HN="))
590 ident->host = strdup(item + strcspn(cp, "=") + 1);
591 else if (strstr(item, "RN="))
592 ident->realname = strdup(item + strcspn(cp, "=") + 1);
593 else if (strstr(item, "E="))
594 ident->email = strdup(item + strcspn(cp, "=") + 1);
595 else if (strstr(item, "O="))
596 ident->org = strdup(item + strcspn(cp, "=") + 1);
597 else if (strstr(item, "C="))
598 ident->country = strdup(item + strcspn(cp, "=") + 1);
613 /* Free's decoded public key identifier context. Call this to free the
614 context returned by the silc_pkcs_decode_identifier. */
616 void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier)
618 silc_free(identifier->username);
619 silc_free(identifier->host);
620 silc_free(identifier->realname);
621 silc_free(identifier->email);
622 silc_free(identifier->org);
623 silc_free(identifier->country);
624 silc_free(identifier);
627 /* Allocates SILC style public key formed from sent arguments. All data
630 SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
631 const char *identifier,
632 const unsigned char *pk,
635 SilcPublicKey public_key;
638 public_key = silc_calloc(1, sizeof(*public_key));
639 public_key->name = strdup(name);
640 public_key->pk_len = pk_len;
641 public_key->pk = silc_memdup(pk, pk_len);
642 public_key->pk_type = SILC_SKE_PK_TYPE_SILC;
644 if (!silc_utf8_valid(identifier, strlen(identifier))) {
645 int len = silc_utf8_encoded_len(identifier, strlen(identifier), 0);
646 tmp = silc_calloc(len + 1, sizeof(*tmp));
647 silc_utf8_encode(identifier, strlen(identifier), 0, tmp, len);
651 public_key->identifier = strdup(identifier);
652 public_key->len = 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
658 /* Free's public key */
660 void silc_pkcs_public_key_free(SilcPublicKey public_key)
663 silc_free(public_key->name);
664 silc_free(public_key->identifier);
665 silc_free(public_key->pk);
666 silc_free(public_key);
670 /* Allocates SILC private key formed from sent arguments. All data is
673 SilcPrivateKey silc_pkcs_private_key_alloc(const char *name,
674 const unsigned char *prv,
677 SilcPrivateKey private_key;
679 private_key = silc_calloc(1, sizeof(*private_key));
680 private_key->name = strdup(name);
681 private_key->prv_len = prv_len;
682 private_key->prv = silc_memdup(prv, prv_len);
687 /* Free's private key */
689 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
692 silc_free(private_key->name);
693 if (private_key->prv) {
694 memset(private_key->prv, 0, private_key->prv_len);
695 silc_free(private_key->prv);
697 silc_free(private_key);
701 /* Encodes SILC style public key from SilcPublicKey. Returns the encoded
705 silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len)
707 return silc_pkcs_public_key_data_encode(public_key->pk,
710 public_key->identifier, len);
713 /* Encodes SILC style public key. Returns the encoded data. */
716 silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
717 char *pkcs, char *identifier,
724 totlen = 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
725 buf = silc_buffer_alloc_size(totlen + 4);
729 silc_buffer_format(buf,
730 SILC_STR_UI_INT(totlen),
731 SILC_STR_UI_SHORT(strlen(pkcs)),
732 SILC_STR_UI32_STRING(pkcs),
733 SILC_STR_UI_SHORT(strlen(identifier)),
734 SILC_STR_UI32_STRING(identifier),
735 SILC_STR_UI_XNSTRING(pk, pk_len),
738 ret = silc_buffer_steal(buf, len);
739 silc_buffer_free(buf);
743 /* Decodes SILC style public key. Returns TRUE if the decoding was
744 successful. Allocates new public key as well. */
746 bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
747 SilcPublicKey *public_key)
749 SilcBufferStruct buf;
751 SilcUInt16 pkcs_len, identifier_len;
752 SilcUInt32 totlen, key_len;
753 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
756 silc_buffer_set(&buf, data, data_len);
759 ret = silc_buffer_unformat(&buf,
760 SILC_STR_UI_INT(&totlen),
765 #if 1 /* Backwards support, remove! */
766 if (totlen == data_len)
770 if (totlen + 4 != data_len)
773 /* Get algorithm name and identifier */
774 silc_buffer_pull(&buf, 4);
776 silc_buffer_unformat(&buf,
777 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
778 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
783 if (pkcs_len < 1 || identifier_len < 3 ||
784 pkcs_len + identifier_len > totlen)
787 /* See if we support this algorithm (check only if PKCS are registered) */
788 if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
789 SILC_LOG_DEBUG(("Unknown PKCS %s", pkcs_name));
793 /* Protocol says that at least UN and HN must be provided as identifier,
795 if (!strstr(ident, "UN=") && !strstr(ident, "HN=")) {
796 SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
801 /* Get key data. We assume that rest of the buffer is key data. */
802 silc_buffer_pull(&buf, 2 + pkcs_len + 2 + identifier_len);
803 key_len = silc_buffer_len(&buf);
804 ret = silc_buffer_unformat(&buf,
805 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
810 /* Try to set the key. If this fails the key must be malformed. This
811 code assumes that the PKCS routine checks the format of the key.
812 (check only if PKCS are registered) */
813 if (SILC_PKCS_LIST) {
814 silc_pkcs_alloc(pkcs_name, &alg);
815 if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
821 *public_key = silc_calloc(1, sizeof(**public_key));
822 (*public_key)->len = totlen;
823 (*public_key)->name = pkcs_name;
824 (*public_key)->identifier = ident;
825 (*public_key)->pk = key_data;
826 (*public_key)->pk_len = key_len;
827 (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
833 silc_free(pkcs_name);
839 /* Encodes Public Key Payload for transmitting public keys and certificates. */
841 SilcBuffer silc_pkcs_public_key_payload_encode(SilcPublicKey public_key)
850 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
854 buffer = silc_buffer_alloc_size(4 + pk_len);
860 silc_buffer_format(buffer,
861 SILC_STR_UI_SHORT(pk_len),
862 SILC_STR_UI_SHORT(public_key->pk_type),
863 SILC_STR_UI_XNSTRING(pk, pk_len),
870 /* Decode Public Key Payload and decodes the public key inside it to
873 bool silc_pkcs_public_key_payload_decode(unsigned char *data,
875 SilcPublicKey *public_key)
877 SilcBufferStruct buf;
878 SilcUInt16 pk_len, pk_type;
885 silc_buffer_set(&buf, data, data_len);
886 ret = silc_buffer_unformat(&buf,
887 SILC_STR_UI_SHORT(&pk_len),
888 SILC_STR_UI_SHORT(&pk_type),
890 if (ret < 0 || pk_len > data_len - 4)
893 /* For now we support only SILC public keys */
894 if (pk_type != SILC_SKE_PK_TYPE_SILC)
897 silc_buffer_pull(&buf, 4);
898 ret = silc_buffer_unformat(&buf,
899 SILC_STR_UI_XNSTRING(&pk, pk_len),
901 silc_buffer_push(&buf, 4);
905 if (!silc_pkcs_public_key_decode(pk, pk_len, public_key))
907 (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
912 /* Compares two public keys and returns TRUE if they are same key, and
913 FALSE if they are not same. */
915 bool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
920 if (key1->len == key2->len &&
921 key1->name && key2->name && key1->identifier && key2->identifier &&
922 !strcmp(key1->name, key2->name) &&
923 !strcmp(key1->identifier, key2->identifier) &&
924 !memcmp(key1->pk, key2->pk, key1->pk_len) &&
925 key1->pk_len == key2->pk_len)
931 /* Copies the public key indicated by `public_key' and returns new allocated
932 public key which is indentical to the `public_key'. */
934 SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
936 SilcPublicKey key = silc_calloc(1, sizeof(*key));
940 key->len = public_key->len;
941 key->name = silc_memdup(public_key->name, strlen(public_key->name));
942 key->identifier = silc_memdup(public_key->identifier,
943 strlen(public_key->identifier));
944 key->pk = silc_memdup(public_key->pk, public_key->pk_len);
945 key->pk_len = public_key->pk_len;
946 key->pk_type = public_key->pk_type;
951 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
954 silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
956 return silc_pkcs_private_key_data_encode(private_key->prv,
957 private_key->prv_len,
958 private_key->name, len);
961 /* Encodes SILC private key. Returns the encoded data. */
964 silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
965 char *pkcs, SilcUInt32 *len)
971 totlen = 2 + strlen(pkcs) + prv_len;
972 buf = silc_buffer_alloc_size(totlen);
976 silc_buffer_format(buf,
977 SILC_STR_UI_SHORT(strlen(pkcs)),
978 SILC_STR_UI32_STRING(pkcs),
979 SILC_STR_UI_XNSTRING(prv, prv_len),
982 ret = silc_buffer_steal(buf, len);
983 silc_buffer_free(buf);
987 /* Decodes SILC style private key. Returns TRUE if the decoding was
988 successful. Allocates new private key as well. */
990 bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
991 SilcPrivateKey *private_key)
993 SilcBufferStruct buf;
997 unsigned char *pkcs_name = NULL, *key_data = NULL;
1000 silc_buffer_set(&buf, data, data_len);
1002 /* Get algorithm name and identifier */
1004 silc_buffer_unformat(&buf,
1005 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
1008 SILC_LOG_DEBUG(("Cannot decode private key buffer"));
1012 if (pkcs_len < 1 || pkcs_len > silc_buffer_truelen(&buf)) {
1013 SILC_LOG_DEBUG(("Malformed private key buffer"));
1017 /* See if we support this algorithm (check only if PKCS are registered). */
1018 if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
1019 SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
1023 /* Get key data. We assume that rest of the buffer is key data. */
1024 silc_buffer_pull(&buf, 2 + pkcs_len);
1025 key_len = silc_buffer_len(&buf);
1026 ret = silc_buffer_unformat(&buf,
1027 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
1032 /* Try to set the key. If this fails the key must be malformed. This
1033 code assumes that the PKCS routine checks the format of the key.
1034 (check only if PKCS are registered) */
1035 if (SILC_PKCS_LIST) {
1036 silc_pkcs_alloc(pkcs_name, &alg);
1037 if (!alg->pkcs->set_private_key(alg->context, key_data, key_len)) {
1038 SILC_LOG_DEBUG(("Could not set private key data"));
1041 silc_pkcs_free(alg);
1045 *private_key = silc_calloc(1, sizeof(**private_key));
1046 (*private_key)->name = pkcs_name;
1047 (*private_key)->prv = key_data;
1048 (*private_key)->prv_len = key_len;
1054 silc_free(pkcs_name);
1055 silc_free(key_data);
1059 /* Internal routine to save public key */
1061 static bool silc_pkcs_save_public_key_internal(const char *filename,
1062 unsigned char *data,
1063 SilcUInt32 data_len,
1064 SilcUInt32 encoding)
1068 unsigned char *tmp = NULL;
1071 case SILC_PKCS_FILE_BIN:
1073 case SILC_PKCS_FILE_PEM:
1074 tmp = data = silc_pem_encode_file(data, data_len);
1075 data_len = strlen(data);
1079 len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1080 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1081 buf = silc_buffer_alloc_size(len);
1087 silc_buffer_format(buf,
1088 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
1089 SILC_STR_UI_XNSTRING(data, data_len),
1090 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
1093 /* Save into file */
1094 if (silc_file_writefile(filename, buf->data, silc_buffer_len(buf))) {
1096 silc_buffer_free(buf);
1101 silc_buffer_free(buf);
1105 /* Saves public key into file */
1107 bool silc_pkcs_save_public_key(const char *filename, SilcPublicKey public_key,
1108 SilcUInt32 encoding)
1110 unsigned char *data;
1111 SilcUInt32 data_len;
1114 data = silc_pkcs_public_key_encode(public_key, &data_len);
1115 ret = silc_pkcs_save_public_key_internal(filename, data, data_len,
1121 /* Saves public key into file */
1123 bool silc_pkcs_save_public_key_data(const char *filename, unsigned char *data,
1124 SilcUInt32 data_len, SilcUInt32 encoding)
1126 return silc_pkcs_save_public_key_internal(filename, data, data_len,
1130 #define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
1132 /* Internal routine to save private key. */
1134 static bool silc_pkcs_save_private_key_internal(const char *filename,
1135 unsigned char *data,
1136 SilcUInt32 data_len,
1139 SilcUInt32 encoding)
1144 SilcBuffer buf, enc;
1145 SilcUInt32 len, blocklen, padlen;
1146 unsigned char tmp[32], keymat[64];
1149 memset(tmp, 0, sizeof(tmp));
1150 memset(keymat, 0, sizeof(keymat));
1152 /* Allocate the AES cipher */
1153 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1154 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1157 blocklen = silc_cipher_get_block_len(aes);
1158 if (blocklen * 2 > sizeof(tmp))
1161 /* Allocate SHA1 hash */
1162 if (!silc_hash_alloc("sha1", &sha1)) {
1163 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1164 silc_cipher_free(aes);
1169 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1170 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1171 silc_hash_free(sha1);
1172 silc_cipher_free(aes);
1176 /* Derive the encryption key from the provided key material. The key
1177 is 256 bits length, and derived by taking hash of the data, then
1178 re-hashing the data and the previous digest, and using the first and
1179 second digest as the key. */
1180 silc_hash_init(sha1);
1181 silc_hash_update(sha1, key, key_len);
1182 silc_hash_final(sha1, keymat);
1183 silc_hash_init(sha1);
1184 silc_hash_update(sha1, key, key_len);
1185 silc_hash_update(sha1, keymat, 16);
1186 silc_hash_final(sha1, keymat + 16);
1188 /* Set the key to the cipher */
1189 silc_cipher_set_key(aes, keymat, 256);
1191 /* Encode the buffer to be encrypted. Add padding to it too, at least
1192 block size of the cipher. */
1194 /* Allocate buffer for encryption */
1195 len = silc_hmac_len(sha1hmac);
1196 padlen = 16 + (16 - ((data_len + 4) % blocklen));
1197 enc = silc_buffer_alloc_size(4 + 4 + data_len + padlen + len);
1199 silc_hmac_free(sha1hmac);
1200 silc_hash_free(sha1);
1201 silc_cipher_free(aes);
1205 /* Generate padding */
1206 for (i = 0; i < padlen; i++)
1207 tmp[i] = silc_rng_global_get_byte_fast();
1209 /* Put magic number */
1210 SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
1211 silc_buffer_pull(enc, 4);
1213 /* Encode the buffer */
1214 silc_buffer_format(enc,
1215 SILC_STR_UI_INT(data_len),
1216 SILC_STR_UI_XNSTRING(data, data_len),
1217 SILC_STR_UI_XNSTRING(tmp, padlen),
1221 silc_cipher_encrypt(aes, enc->data, enc->data, silc_buffer_len(enc) - len,
1222 silc_cipher_get_iv(aes));
1224 silc_buffer_push(enc, 4);
1226 /* Compute HMAC over the encrypted data and append the MAC to data.
1227 The key is the first digest of the original key material. */
1228 data_len = silc_buffer_len(enc) - len;
1229 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1230 silc_hmac_update(sha1hmac, enc->data, data_len);
1231 silc_buffer_pull(enc, data_len);
1232 silc_hmac_final(sha1hmac, enc->data, NULL);
1233 silc_buffer_push(enc, data_len);
1236 memset(keymat, 0, sizeof(keymat));
1237 memset(tmp, 0, sizeof(tmp));
1238 silc_hmac_free(sha1hmac);
1239 silc_hash_free(sha1);
1240 silc_cipher_free(aes);
1243 data_len = silc_buffer_len(enc);
1246 case SILC_PKCS_FILE_BIN:
1248 case SILC_PKCS_FILE_PEM:
1249 data = silc_pem_encode_file(data, data_len);
1250 data_len = strlen(data);
1254 /* Encode the data and save to file */
1255 len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1256 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1257 buf = silc_buffer_alloc_size(len);
1258 silc_buffer_format(buf,
1259 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
1260 SILC_STR_UI_XNSTRING(data, data_len),
1261 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
1264 /* Save into a file */
1265 if (silc_file_writefile_mode(filename, buf->data,
1266 silc_buffer_len(buf), 0600)) {
1267 silc_buffer_clear(buf);
1268 silc_buffer_free(buf);
1269 silc_buffer_clear(enc);
1270 silc_buffer_free(enc);
1274 silc_buffer_clear(buf);
1275 silc_buffer_free(buf);
1276 silc_buffer_clear(enc);
1277 silc_buffer_free(enc);
1281 /* Saves private key into file. */
1283 bool silc_pkcs_save_private_key(const char *filename,
1284 SilcPrivateKey private_key,
1285 unsigned char *passphrase,
1286 SilcUInt32 passphrase_len,
1287 SilcUInt32 encoding)
1289 unsigned char *data;
1290 SilcUInt32 data_len;
1293 data = silc_pkcs_private_key_encode(private_key, &data_len);
1294 ret = silc_pkcs_save_private_key_internal(filename, data, data_len,
1295 passphrase, passphrase_len,
1297 memset(data, 0, data_len);
1302 /* Loads public key from file and allocates new public key. Returns TRUE
1303 if loading was successful. */
1305 bool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key,
1306 SilcUInt32 encoding)
1308 unsigned char *cp, *old, *data, byte;
1309 SilcUInt32 i, data_len, len;
1311 SILC_LOG_DEBUG(("Loading public key `%s' with %s encoding", filename,
1312 encoding == SILC_PKCS_FILE_PEM ? "Base64" :
1313 encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
1315 old = data = silc_file_readfile(filename, &data_len);
1319 /* Check start of file and remove header from the data. */
1320 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
1322 for (i = 0; i < len; i++) {
1325 if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
1326 memset(old, 0, data_len);
1333 /* Decode public key */
1335 len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1336 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1339 case SILC_PKCS_FILE_BIN:
1341 case SILC_PKCS_FILE_PEM:
1342 data = silc_pem_decode(data, len, &len);
1343 memset(old, 0, data_len);
1350 if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
1351 memset(old, 0, data_len);
1357 memset(old, 0, data_len);
1362 /* Load private key from file and allocates new private key. Returns TRUE
1363 if loading was successful. */
1365 bool silc_pkcs_load_private_key(const char *filename,
1366 SilcPrivateKey *private_key,
1367 unsigned char *passphrase,
1368 SilcUInt32 passphrase_len,
1369 SilcUInt32 encoding)
1374 SilcUInt32 blocklen;
1375 unsigned char tmp[32], keymat[64];
1376 unsigned char *cp, *old, *data, byte;
1377 SilcUInt32 i, data_len, len, magic, mac_len;
1379 SILC_LOG_DEBUG(("Loading private key `%s' with %s encoding", filename,
1380 encoding == SILC_PKCS_FILE_PEM ? "Base64" :
1381 encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
1383 old = data = silc_file_readfile(filename, &data_len);
1387 /* Check start of file and remove header from the data. */
1388 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
1390 for (i = 0; i < len; i++) {
1393 if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
1394 memset(old, 0, data_len);
1401 /* Decode private key */
1402 len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1403 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1406 case SILC_PKCS_FILE_BIN:
1408 case SILC_PKCS_FILE_PEM:
1409 data = silc_pem_decode(data, len, &len);
1411 memset(old, 0, data_len);
1418 memset(tmp, 0, sizeof(tmp));
1419 memset(keymat, 0, sizeof(keymat));
1421 /* Private key files without the specific magic number are assumed
1422 to be the old-style private keys that are not encrypted. */
1423 SILC_GET32_MSB(magic, data);
1424 if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
1425 SILC_LOG_DEBUG(("Private key does not have correct magic!"));
1427 /* Now decode the actual private key */
1428 if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1429 memset(old, 0, data_len);
1434 memset(old, 0, data_len);
1439 /* Allocate the AES cipher */
1440 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1441 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1442 memset(old, 0, data_len);
1446 blocklen = silc_cipher_get_block_len(aes);
1447 if (blocklen * 2 > sizeof(tmp)) {
1448 memset(old, 0, data_len);
1453 /* Allocate SHA1 hash */
1454 if (!silc_hash_alloc("sha1", &sha1)) {
1455 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1456 silc_cipher_free(aes);
1457 memset(old, 0, data_len);
1463 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1464 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1465 silc_hash_free(sha1);
1466 silc_cipher_free(aes);
1467 memset(old, 0, data_len);
1472 /* Derive the decryption key from the provided key material. The key
1473 is 256 bits length, and derived by taking hash of the data, then
1474 re-hashing the data and the previous digest, and using the first and
1475 second digest as the key. */
1476 silc_hash_init(sha1);
1477 silc_hash_update(sha1, passphrase, passphrase_len);
1478 silc_hash_final(sha1, keymat);
1479 silc_hash_init(sha1);
1480 silc_hash_update(sha1, passphrase, passphrase_len);
1481 silc_hash_update(sha1, keymat, 16);
1482 silc_hash_final(sha1, keymat + 16);
1484 /* Set the key to the cipher */
1485 silc_cipher_set_key(aes, keymat, 256);
1487 /* First, verify the MAC of the private key data */
1488 mac_len = silc_hmac_len(sha1hmac);
1489 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1490 silc_hmac_update(sha1hmac, data, len - mac_len);
1491 silc_hmac_final(sha1hmac, tmp, NULL);
1492 if (memcmp(tmp, data + (len - mac_len), mac_len)) {
1493 SILC_LOG_DEBUG(("Integrity check for private key failed"));
1494 memset(keymat, 0, sizeof(keymat));
1495 memset(tmp, 0, sizeof(tmp));
1496 silc_hmac_free(sha1hmac);
1497 silc_hash_free(sha1);
1498 silc_cipher_free(aes);
1499 memset(old, 0, data_len);
1506 /* Decrypt the private key buffer */
1507 silc_cipher_decrypt(aes, data, data, len - mac_len, NULL);
1508 SILC_GET32_MSB(i, data);
1510 SILC_LOG_DEBUG(("Bad private key length in buffer!"));
1511 memset(keymat, 0, sizeof(keymat));
1512 memset(tmp, 0, sizeof(tmp));
1513 silc_hmac_free(sha1hmac);
1514 silc_hash_free(sha1);
1515 silc_cipher_free(aes);
1516 memset(old, 0, data_len);
1524 memset(keymat, 0, sizeof(keymat));
1525 memset(tmp, 0, sizeof(tmp));
1526 silc_hmac_free(sha1hmac);
1527 silc_hash_free(sha1);
1528 silc_cipher_free(aes);
1530 /* Now decode the actual private key */
1531 if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1532 memset(old, 0, data_len);
1537 memset(old, 0, data_len);