5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 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"
26 /* The main SILC PKCS structure. */
27 struct SilcPKCSStruct {
28 void *context; /* Algorithm internal context */
29 SilcPKCSObject *pkcs; /* Algorithm implementation */
30 SilcUInt32 key_len; /* Key length in bits */
34 /* Dynamically registered list of PKCS. */
35 SilcDList silc_pkcs_list = NULL;
36 #define SILC_PKCS_LIST silc_pkcs_list
38 #define SILC_PKCS_LIST TRUE
39 #endif /* SILC_EPOC */
41 /* Static list of PKCS for silc_pkcs_register_default(). */
42 const SilcPKCSObject silc_default_pkcs[] =
44 /* RSA with PKCS #1 (Uses directly routines from Raw RSA operations) */
46 silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
47 silc_rsa_get_private_key, silc_rsa_set_public_key,
48 silc_rsa_set_private_key, silc_rsa_context_len,
49 silc_pkcs1_encrypt, silc_pkcs1_decrypt,
50 silc_pkcs1_sign, silc_pkcs1_verify },
52 /* Raw RSA operations */
54 silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
55 silc_rsa_get_private_key, silc_rsa_set_public_key,
56 silc_rsa_set_private_key, silc_rsa_context_len,
57 silc_rsa_encrypt, silc_rsa_decrypt,
58 silc_rsa_sign, silc_rsa_verify },
60 { NULL, NULL, NULL, NULL, NULL,
61 NULL, NULL, NULL, NULL, NULL, NULL }
64 /* Register a new PKCS into SILC. This is used at the initialization of
67 bool silc_pkcs_register(const SilcPKCSObject *pkcs)
72 SILC_LOG_DEBUG(("Registering new PKCS `%s'", pkcs->name));
74 /* Check if exists already */
76 SilcPKCSObject *entry;
77 silc_dlist_start(silc_pkcs_list);
78 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
79 if (!strcmp(entry->name, pkcs->name))
84 new = silc_calloc(1, sizeof(*new));
85 new->name = strdup(pkcs->name);
86 new->init = pkcs->init;
87 new->clear_keys = pkcs->clear_keys;
88 new->get_public_key = pkcs->get_public_key;
89 new->get_private_key = pkcs->get_private_key;
90 new->set_public_key = pkcs->set_public_key;
91 new->set_private_key = pkcs->set_private_key;
92 new->context_len = pkcs->context_len;
93 new->encrypt = pkcs->encrypt;
94 new->decrypt = pkcs->decrypt;
95 new->sign = pkcs->sign;
96 new->verify = pkcs->verify;
99 if (silc_pkcs_list == NULL)
100 silc_pkcs_list = silc_dlist_init();
101 silc_dlist_add(silc_pkcs_list, new);
103 #endif /* SILC_EPOC */
107 /* Unregister a PKCS from the SILC. */
109 bool silc_pkcs_unregister(SilcPKCSObject *pkcs)
112 SilcPKCSObject *entry;
114 SILC_LOG_DEBUG(("Unregistering PKCS"));
119 silc_dlist_start(silc_pkcs_list);
120 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
121 if (pkcs == SILC_ALL_PKCS || entry == pkcs) {
122 silc_dlist_del(silc_pkcs_list, entry);
123 silc_free(entry->name);
126 if (silc_dlist_count(silc_pkcs_list) == 0) {
127 silc_dlist_uninit(silc_pkcs_list);
128 silc_pkcs_list = NULL;
135 #endif /* SILC_EPOC */
139 /* Function that registers all the default PKCS (all builtin PKCS).
140 The application may use this to register the default PKCS if specific
141 PKCS in any specific order is not wanted. */
143 bool silc_pkcs_register_default(void)
148 for (i = 0; silc_default_pkcs[i].name; i++)
149 silc_pkcs_register(&(silc_default_pkcs[i]));
151 #endif /* SILC_EPOC */
155 bool silc_pkcs_unregister_all(void)
158 SilcPKCSObject *entry;
163 silc_dlist_start(silc_pkcs_list);
164 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
165 silc_pkcs_unregister(entry);
169 #endif /* SILC_EPOC */
173 /* Allocates a new SilcPKCS object. The new allocated object is returned
174 to the 'new_pkcs' argument. */
176 bool silc_pkcs_alloc(const unsigned char *name, SilcPKCS *new_pkcs)
178 SilcPKCSObject *entry = NULL;
180 SILC_LOG_DEBUG(("Allocating new PKCS object"));
183 if (silc_pkcs_list) {
184 silc_dlist_start(silc_pkcs_list);
185 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
186 if (!strcmp(entry->name, name))
192 /* On EPOC which don't have globals we check our constant hash list. */
194 for (i = 0; silc_default_pkcs[i].name; i++) {
195 if (!strcmp(silc_default_pkcs[i].name, name)) {
196 entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
201 #endif /* SILC_EPOC */
204 *new_pkcs = silc_calloc(1, sizeof(**new_pkcs));
205 (*new_pkcs)->pkcs = entry;
206 (*new_pkcs)->context = silc_calloc(1, entry->context_len());
213 /* Free's the PKCS object */
215 void silc_pkcs_free(SilcPKCS pkcs)
218 pkcs->pkcs->clear_keys(pkcs->context);
219 silc_free(pkcs->context);
224 /* Return TRUE if PKCS algorithm `name' is supported. */
226 bool silc_pkcs_is_supported(const unsigned char *name)
229 SilcPKCSObject *entry;
231 if (silc_pkcs_list) {
232 silc_dlist_start(silc_pkcs_list);
233 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
234 if (!strcmp(entry->name, name))
241 for (i = 0; silc_default_pkcs[i].name; i++)
242 if (!strcmp(silc_default_pkcs[i].name, name))
245 #endif /* SILC_EPOC */
249 /* Returns comma separated list of supported PKCS algorithms */
251 char *silc_pkcs_get_supported(void)
253 SilcPKCSObject *entry;
258 if (silc_pkcs_list) {
259 silc_dlist_start(silc_pkcs_list);
260 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
261 len += strlen(entry->name);
262 list = silc_realloc(list, len + 1);
264 memcpy(list + (len - strlen(entry->name)),
265 entry->name, strlen(entry->name));
266 memcpy(list + len, ",", 1);
273 for (i = 0; silc_default_pkcs[i].name; i++) {
274 entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
275 len += strlen(entry->name);
276 list = silc_realloc(list, len + 1);
278 memcpy(list + (len - strlen(entry->name)),
279 entry->name, strlen(entry->name));
280 memcpy(list + len, ",", 1);
284 #endif /* SILC_EPOC */
291 /* Generate new key pair into the `pkcs' context. */
293 bool silc_pkcs_generate_key(SilcPKCS pkcs, SilcUInt32 bits_key_len,
296 return pkcs->pkcs->init(pkcs->context, bits_key_len, rng);
299 /* Returns the length of the key */
301 SilcUInt32 silc_pkcs_get_key_len(SilcPKCS pkcs)
303 return pkcs->key_len;
306 const char *silc_pkcs_get_name(SilcPKCS pkcs)
308 return pkcs->pkcs->name;
311 /* Returns SILC style public key */
313 unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, SilcUInt32 *len)
315 return pkcs->pkcs->get_public_key(pkcs->context, len);
318 /* Returns SILC style private key */
320 unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, SilcUInt32 *len)
322 return pkcs->pkcs->get_private_key(pkcs->context, len);
325 /* Sets public key from SilcPublicKey. */
327 SilcUInt32 silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
329 pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
331 return pkcs->key_len;
334 /* Sets public key from data. */
336 SilcUInt32 silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
339 pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, pk, pk_len);
340 return pkcs->key_len;
343 /* Sets private key from SilcPrivateKey. */
345 SilcUInt32 silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
348 key_len = pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
349 private_key->prv_len);
351 pkcs->key_len = key_len;
352 return pkcs->key_len;
355 /* Sets private key from data. */
357 SilcUInt32 silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
361 key_len = pkcs->pkcs->set_private_key(pkcs->context, prv, prv_len);
363 pkcs->key_len = key_len;
364 return pkcs->key_len;
369 bool silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
370 unsigned char *dst, SilcUInt32 *dst_len)
372 return pkcs->pkcs->encrypt(pkcs->context, src, src_len, dst, dst_len);
377 bool silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
378 unsigned char *dst, SilcUInt32 *dst_len)
380 return pkcs->pkcs->decrypt(pkcs->context, src, src_len, dst, dst_len);
383 /* Generates signature */
385 bool silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
386 unsigned char *dst, SilcUInt32 *dst_len)
388 return pkcs->pkcs->sign(pkcs->context, src, src_len, dst, dst_len);
391 /* Verifies signature */
393 bool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
394 SilcUInt32 signature_len, unsigned char *data,
397 return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
401 /* Generates signature with hash. The hash is signed. */
403 bool silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
404 unsigned char *src, SilcUInt32 src_len,
405 unsigned char *dst, SilcUInt32 *dst_len)
407 unsigned char hashr[32];
411 silc_hash_make(hash, src, src_len, hashr);
412 hash_len = silc_hash_len(hash);
414 SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
416 ret = pkcs->pkcs->sign(pkcs->context, hashr, hash_len, dst, dst_len);
417 memset(hashr, 0, sizeof(hashr));
422 /* Verifies signature with hash. The `data' is hashed and verified against
425 bool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
426 unsigned char *signature,
427 SilcUInt32 signature_len,
431 unsigned char hashr[32];
435 silc_hash_make(hash, data, data_len, hashr);
436 hash_len = silc_hash_len(hash);
438 SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
440 ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
442 memset(hashr, 0, sizeof(hashr));
447 /* Encodes and returns SILC public key identifier. If some of the
448 arguments is NULL those are not encoded into the identifier string.
449 Protocol says that at least username and host must be provided. */
451 char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
452 char *email, char *org, char *country)
456 SilcUInt32 len, tlen = 0;
458 if (!username || !host)
461 len = (username ? strlen(username) : 0) +
462 (host ? strlen(host) : 0) +
463 (realname ? strlen(realname) : 0) +
464 (email ? strlen(email) : 0) +
465 (org ? strlen(org) : 0) +
466 (country ? strlen(country) : 0);
471 len += 3 + 5 + 5 + 4 + 4 + 4;
472 buf = silc_buffer_alloc(len);
473 silc_buffer_pull_tail(buf, len);
476 silc_buffer_format(buf,
477 SILC_STR_UI32_STRING("UN="),
478 SILC_STR_UI32_STRING(username),
480 silc_buffer_pull(buf, 3 + strlen(username));
481 tlen = 3 + strlen(username);
485 silc_buffer_format(buf,
486 SILC_STR_UI32_STRING(", "),
487 SILC_STR_UI32_STRING("HN="),
488 SILC_STR_UI32_STRING(host),
490 silc_buffer_pull(buf, 5 + strlen(host));
491 tlen += 5 + strlen(host);
495 silc_buffer_format(buf,
496 SILC_STR_UI32_STRING(", "),
497 SILC_STR_UI32_STRING("RN="),
498 SILC_STR_UI32_STRING(realname),
500 silc_buffer_pull(buf, 5 + strlen(realname));
501 tlen += 5 + strlen(realname);
505 silc_buffer_format(buf,
506 SILC_STR_UI32_STRING(", "),
507 SILC_STR_UI32_STRING("E="),
508 SILC_STR_UI32_STRING(email),
510 silc_buffer_pull(buf, 4 + strlen(email));
511 tlen += 4 + strlen(email);
515 silc_buffer_format(buf,
516 SILC_STR_UI32_STRING(", "),
517 SILC_STR_UI32_STRING("O="),
518 SILC_STR_UI32_STRING(org),
520 silc_buffer_pull(buf, 4 + strlen(org));
521 tlen += 4 + strlen(org);
525 silc_buffer_format(buf,
526 SILC_STR_UI32_STRING(", "),
527 SILC_STR_UI32_STRING("C="),
528 SILC_STR_UI32_STRING(country),
530 silc_buffer_pull(buf, 4 + strlen(country));
531 tlen += 4 + strlen(country);
534 silc_buffer_push(buf, buf->data - buf->head);
535 identifier = silc_calloc(tlen + 1, sizeof(*identifier));
536 memcpy(identifier, buf->data, tlen);
537 silc_buffer_free(buf);
542 /* Decodes the provided `identifier' and returns allocated context for
545 SilcPublicKeyIdentifier silc_pkcs_decode_identifier(char *identifier)
547 SilcPublicKeyIdentifier ident;
551 ident = silc_calloc(1, sizeof(*ident));
555 len = strcspn(cp, ",");
556 if (len - 1 >= 0 && cp[len - 1] == '\\') {
559 len = strcspn(cp, ",") + len;
560 if (len - 1 >= 0 && cp[len - 1] != '\\')
565 item = silc_calloc(len + 1, sizeof(char));
566 memcpy(item, cp, len);
568 if (strstr(item, "UN="))
569 ident->username = strdup(item + strcspn(cp, "=") + 1);
570 else if (strstr(item, "HN="))
571 ident->host = strdup(item + strcspn(cp, "=") + 1);
572 else if (strstr(item, "RN="))
573 ident->realname = strdup(item + strcspn(cp, "=") + 1);
574 else if (strstr(item, "E="))
575 ident->email = strdup(item + strcspn(cp, "=") + 1);
576 else if (strstr(item, "O="))
577 ident->org = strdup(item + strcspn(cp, "=") + 1);
578 else if (strstr(item, "C="))
579 ident->country = strdup(item + strcspn(cp, "=") + 1);
594 /* Free's decoded public key identifier context. Call this to free the
595 context returned by the silc_pkcs_decode_identifier. */
597 void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier)
599 silc_free(identifier->username);
600 silc_free(identifier->host);
601 silc_free(identifier->realname);
602 silc_free(identifier->email);
603 silc_free(identifier->org);
604 silc_free(identifier->country);
605 silc_free(identifier);
608 /* Allocates SILC style public key formed from sent arguments. All data
611 SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
612 const char *identifier,
613 const unsigned char *pk,
616 SilcPublicKey public_key;
619 public_key = silc_calloc(1, sizeof(*public_key));
620 public_key->name = strdup(name);
621 public_key->pk_len = pk_len;
622 public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
623 public_key->pk_type = SILC_SKE_PK_TYPE_SILC;
624 memcpy(public_key->pk, pk, pk_len);
626 if (!silc_utf8_valid(identifier, strlen(identifier))) {
627 int len = silc_utf8_encoded_len(identifier, strlen(identifier), 0);
628 tmp = silc_calloc(len + 1, sizeof(*tmp));
629 silc_utf8_encode(identifier, strlen(identifier), 0, tmp, len);
633 public_key->identifier = strdup(identifier);
634 public_key->len = 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
640 /* Free's public key */
642 void silc_pkcs_public_key_free(SilcPublicKey public_key)
645 silc_free(public_key->name);
646 silc_free(public_key->identifier);
647 silc_free(public_key->pk);
648 silc_free(public_key);
652 /* Allocates SILC private key formed from sent arguments. All data is
655 SilcPrivateKey silc_pkcs_private_key_alloc(const char *name,
656 const unsigned char *prv,
659 SilcPrivateKey private_key;
661 private_key = silc_calloc(1, sizeof(*private_key));
662 private_key->name = strdup(name);
663 private_key->prv_len = prv_len;
664 private_key->prv = silc_calloc(prv_len, sizeof(*private_key->prv));
665 memcpy(private_key->prv, prv, prv_len);
670 /* Free's private key */
672 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
675 silc_free(private_key->name);
676 silc_free(private_key->prv);
677 silc_free(private_key);
681 /* Encodes SILC style public key from SilcPublicKey. Returns the encoded
685 silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len)
690 buf = silc_buffer_alloc_size(public_key->len + 4);
694 silc_buffer_format(buf,
695 SILC_STR_UI_INT(public_key->len),
696 SILC_STR_UI_SHORT(strlen(public_key->name)),
697 SILC_STR_UI32_STRING(public_key->name),
698 SILC_STR_UI_SHORT(strlen(public_key->identifier)),
699 SILC_STR_UI32_STRING(public_key->identifier),
700 SILC_STR_UI_XNSTRING(public_key->pk,
704 ret = silc_buffer_steal(buf, len);
705 silc_buffer_free(buf);
709 /* Encodes SILC style public key. Returns the encoded data. */
712 silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
713 char *pkcs, char *identifier,
720 totlen = 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
721 buf = silc_buffer_alloc_size(totlen + 4);
725 silc_buffer_format(buf,
726 SILC_STR_UI_INT(totlen),
727 SILC_STR_UI_SHORT(strlen(pkcs)),
728 SILC_STR_UI32_STRING(pkcs),
729 SILC_STR_UI_SHORT(strlen(identifier)),
730 SILC_STR_UI32_STRING(identifier),
731 SILC_STR_UI_XNSTRING(pk, pk_len),
734 ret = silc_buffer_steal(buf, len);
735 silc_buffer_free(buf);
739 /* Decodes SILC style public key. Returns TRUE if the decoding was
740 successful. Allocates new public key as well. */
742 bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
743 SilcPublicKey *public_key)
745 SilcBufferStruct buf;
747 SilcUInt16 pkcs_len, identifier_len;
748 SilcUInt32 totlen, key_len;
749 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
752 silc_buffer_set(&buf, data, data_len);
755 ret = silc_buffer_unformat(&buf,
756 SILC_STR_UI_INT(&totlen),
761 #if 1 /* Backwards support, remove! */
762 if (totlen == data_len)
766 if (totlen + 4 != data_len)
769 /* Get algorithm name and identifier */
770 silc_buffer_pull(&buf, 4);
772 silc_buffer_unformat(&buf,
773 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
774 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
779 if (pkcs_len < 1 || identifier_len < 3 ||
780 pkcs_len + identifier_len > totlen)
783 /* See if we support this algorithm (check only if PKCS are registered) */
784 if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
785 SILC_LOG_DEBUG(("Unknown PKCS %s", pkcs_name));
789 /* Protocol says that at least UN and HN must be provided as identifier,
791 if (!strstr(ident, "UN=") && !strstr(ident, "HN=")) {
792 SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
797 /* Get key data. We assume that rest of the buffer is key data. */
798 silc_buffer_pull(&buf, 2 + pkcs_len + 2 + identifier_len);
800 ret = silc_buffer_unformat(&buf,
801 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
806 /* Try to set the key. If this fails the key must be malformed. This
807 code assumes that the PKCS routine checks the format of the key.
808 (check only if PKCS are registered) */
809 if (SILC_PKCS_LIST) {
810 silc_pkcs_alloc(pkcs_name, &alg);
811 if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
817 *public_key = silc_calloc(1, sizeof(**public_key));
818 (*public_key)->len = totlen;
819 (*public_key)->name = pkcs_name;
820 (*public_key)->identifier = ident;
821 (*public_key)->pk = key_data;
822 (*public_key)->pk_len = key_len;
823 (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
829 silc_free(pkcs_name);
835 /* Encodes Public Key Payload for transmitting public keys and certificates. */
837 SilcBuffer silc_pkcs_public_key_payload_encode(SilcPublicKey public_key)
846 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
850 buffer = silc_buffer_alloc_size(4 + pk_len);
856 silc_buffer_format(buffer,
857 SILC_STR_UI_SHORT(pk_len),
858 SILC_STR_UI_SHORT(public_key->pk_type),
859 SILC_STR_UI_XNSTRING(pk, pk_len),
866 /* Decode Public Key Payload and decodes the public key inside it to
869 bool silc_pkcs_public_key_payload_decode(unsigned char *data,
871 SilcPublicKey *public_key)
873 SilcBufferStruct buf;
874 SilcUInt16 pk_len, pk_type;
881 silc_buffer_set(&buf, data, data_len);
882 ret = silc_buffer_unformat(&buf,
883 SILC_STR_UI_SHORT(&pk_len),
884 SILC_STR_UI_SHORT(&pk_type),
886 if (ret < 0 || pk_len > data_len - 4)
889 /* For now we support only SILC public keys */
890 if (pk_type != SILC_SKE_PK_TYPE_SILC)
893 silc_buffer_pull(&buf, 4);
894 ret = silc_buffer_unformat(&buf,
895 SILC_STR_UI_XNSTRING(&pk, pk_len),
897 silc_buffer_push(&buf, 4);
901 if (!silc_pkcs_public_key_decode(pk, pk_len, public_key))
903 (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
908 /* Compares two public keys and returns TRUE if they are same key, and
909 FALSE if they are not same. */
911 bool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
916 if (key1->len == key2->len &&
917 key1->name && key2->name && key1->identifier && key2->identifier &&
918 !strcmp(key1->name, key2->name) &&
919 !strcmp(key1->identifier, key2->identifier) &&
920 !memcmp(key1->pk, key2->pk, key1->pk_len) &&
921 key1->pk_len == key2->pk_len)
927 /* Copies the public key indicated by `public_key' and returns new allocated
928 public key which is indentical to the `public_key'. */
930 SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
932 SilcPublicKey key = silc_calloc(1, sizeof(*key));
936 key->len = public_key->len;
937 key->name = silc_memdup(public_key->name, strlen(public_key->name));
938 key->identifier = silc_memdup(public_key->identifier,
939 strlen(public_key->identifier));
940 key->pk = silc_memdup(public_key->pk, public_key->pk_len);
941 key->pk_len = public_key->pk_len;
942 key->pk_type = public_key->pk_type;
947 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
950 silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
956 totlen = 2 + strlen(private_key->name) + private_key->prv_len;
957 buf = silc_buffer_alloc_size(totlen);
961 silc_buffer_format(buf,
962 SILC_STR_UI_SHORT(strlen(private_key->name)),
963 SILC_STR_UI32_STRING(private_key->name),
964 SILC_STR_UI_XNSTRING(private_key->prv,
965 private_key->prv_len),
968 ret = silc_buffer_steal(buf, len);
969 silc_buffer_free(buf);
973 /* Encodes SILC private key. Returns the encoded data. */
976 silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
977 char *pkcs, SilcUInt32 *len)
983 totlen = 2 + strlen(pkcs) + prv_len;
984 buf = silc_buffer_alloc_size(totlen);
988 silc_buffer_format(buf,
989 SILC_STR_UI_SHORT(strlen(pkcs)),
990 SILC_STR_UI32_STRING(pkcs),
991 SILC_STR_UI_XNSTRING(prv, prv_len),
994 ret = silc_buffer_steal(buf, len);
995 silc_buffer_free(buf);
999 /* Decodes SILC style private key. Returns TRUE if the decoding was
1000 successful. Allocates new private key as well. */
1002 bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
1003 SilcPrivateKey *private_key)
1005 SilcBufferStruct buf;
1007 SilcUInt16 pkcs_len;
1009 unsigned char *pkcs_name = NULL, *key_data = NULL;
1012 silc_buffer_set(&buf, data, data_len);
1014 /* Get algorithm name and identifier */
1016 silc_buffer_unformat(&buf,
1017 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
1020 SILC_LOG_DEBUG(("Cannot decode private key buffer"));
1024 if (pkcs_len < 1 || pkcs_len > buf.truelen) {
1025 SILC_LOG_DEBUG(("Malformed private key buffer"));
1029 /* See if we support this algorithm (check only if PKCS are registered). */
1030 if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
1031 SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
1035 /* Get key data. We assume that rest of the buffer is key data. */
1036 silc_buffer_pull(&buf, 2 + pkcs_len);
1038 ret = silc_buffer_unformat(&buf,
1039 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
1044 /* Try to set the key. If this fails the key must be malformed. This
1045 code assumes that the PKCS routine checks the format of the key.
1046 (check only if PKCS are registered) */
1047 if (SILC_PKCS_LIST) {
1048 silc_pkcs_alloc(pkcs_name, &alg);
1049 if (!alg->pkcs->set_private_key(alg->context, key_data, key_len)) {
1050 SILC_LOG_DEBUG(("Could not set private key data"));
1053 silc_pkcs_free(alg);
1057 *private_key = silc_calloc(1, sizeof(**private_key));
1058 (*private_key)->name = pkcs_name;
1059 (*private_key)->prv = key_data;
1060 (*private_key)->prv_len = key_len;
1066 silc_free(pkcs_name);
1067 silc_free(key_data);
1071 /* Internal routine to save public key */
1073 static bool silc_pkcs_save_public_key_internal(const char *filename,
1074 unsigned char *data,
1075 SilcUInt32 data_len,
1076 SilcUInt32 encoding)
1080 unsigned char *tmp = NULL;
1083 case SILC_PKCS_FILE_BIN:
1085 case SILC_PKCS_FILE_PEM:
1086 tmp = data = silc_pem_encode_file(data, data_len);
1087 data_len = strlen(data);
1091 len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1092 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1093 buf = silc_buffer_alloc_size(len);
1099 silc_buffer_format(buf,
1100 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
1101 SILC_STR_UI_XNSTRING(data, data_len),
1102 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
1105 /* Save into file */
1106 if (silc_file_writefile(filename, buf->data, buf->len)) {
1108 silc_buffer_free(buf);
1113 silc_buffer_free(buf);
1117 /* Saves public key into file */
1119 bool silc_pkcs_save_public_key(const char *filename, SilcPublicKey public_key,
1120 SilcUInt32 encoding)
1122 unsigned char *data;
1123 SilcUInt32 data_len;
1126 data = silc_pkcs_public_key_encode(public_key, &data_len);
1127 ret = silc_pkcs_save_public_key_internal(filename, data, data_len,
1133 /* Saves public key into file */
1135 bool silc_pkcs_save_public_key_data(const char *filename, unsigned char *data,
1136 SilcUInt32 data_len, SilcUInt32 encoding)
1138 return silc_pkcs_save_public_key_internal(filename, data, data_len,
1142 #define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
1144 /* Internal routine to save private key. */
1146 static bool silc_pkcs_save_private_key_internal(const char *filename,
1147 unsigned char *data,
1148 SilcUInt32 data_len,
1151 SilcUInt32 encoding)
1156 SilcBuffer buf, enc;
1157 SilcUInt32 len, blocklen, padlen;
1158 unsigned char tmp[32], keymat[64];
1161 memset(tmp, 0, sizeof(tmp));
1162 memset(keymat, 0, sizeof(keymat));
1164 /* Allocate the AES cipher */
1165 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1166 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1169 blocklen = silc_cipher_get_block_len(aes);
1170 if (blocklen * 2 > sizeof(tmp))
1173 /* Allocate SHA1 hash */
1174 if (!silc_hash_alloc("sha1", &sha1)) {
1175 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1176 silc_cipher_free(aes);
1181 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1182 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1183 silc_hash_free(sha1);
1184 silc_cipher_free(aes);
1188 /* Derive the encryption key from the provided key material. The key
1189 is 256 bits length, and derived by taking hash of the data, then
1190 re-hashing the data and the previous digest, and using the first and
1191 second digest as the key. */
1192 silc_hash_init(sha1);
1193 silc_hash_update(sha1, key, key_len);
1194 silc_hash_final(sha1, keymat);
1195 silc_hash_init(sha1);
1196 silc_hash_update(sha1, key, key_len);
1197 silc_hash_update(sha1, keymat, 16);
1198 silc_hash_final(sha1, keymat + 16);
1200 /* Set the key to the cipher */
1201 silc_cipher_set_key(aes, keymat, 256);
1203 /* Encode the buffer to be encrypted. Add padding to it too, at least
1204 block size of the cipher. */
1206 /* Allocate buffer for encryption */
1207 len = silc_hmac_len(sha1hmac);
1208 padlen = 16 + (16 - ((data_len + 4) % blocklen));
1209 enc = silc_buffer_alloc_size(4 + 4 + data_len + padlen + len);
1211 silc_hmac_free(sha1hmac);
1212 silc_hash_free(sha1);
1213 silc_cipher_free(aes);
1217 /* Generate padding */
1218 for (i = 0; i < padlen; i++)
1219 tmp[i] = silc_rng_global_get_byte_fast();
1221 /* Put magic number */
1222 SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
1223 silc_buffer_pull(enc, 4);
1225 /* Encode the buffer */
1226 silc_buffer_format(enc,
1227 SILC_STR_UI_INT(data_len),
1228 SILC_STR_UI_XNSTRING(data, data_len),
1229 SILC_STR_UI_XNSTRING(tmp, padlen),
1233 silc_cipher_encrypt(aes, enc->data, enc->data, enc->len - len,
1234 silc_cipher_get_iv(aes));
1236 silc_buffer_push(enc, 4);
1238 /* Compute HMAC over the encrypted data and append the MAC to data.
1239 The key is the first digest of the original key material. */
1240 data_len = enc->len - len;
1241 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1242 silc_hmac_update(sha1hmac, enc->data, data_len);
1243 silc_buffer_pull(enc, data_len);
1244 silc_hmac_final(sha1hmac, enc->data, NULL);
1245 silc_buffer_push(enc, data_len);
1248 memset(keymat, 0, sizeof(keymat));
1249 memset(tmp, 0, sizeof(tmp));
1250 silc_hmac_free(sha1hmac);
1251 silc_hash_free(sha1);
1252 silc_cipher_free(aes);
1255 data_len = enc->len;
1258 case SILC_PKCS_FILE_BIN:
1260 case SILC_PKCS_FILE_PEM:
1261 data = silc_pem_encode_file(data, data_len);
1262 data_len = strlen(data);
1266 /* Encode the data and save to file */
1267 len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1268 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1269 buf = silc_buffer_alloc_size(len);
1270 silc_buffer_format(buf,
1271 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
1272 SILC_STR_UI_XNSTRING(data, data_len),
1273 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
1276 /* Save into a file */
1277 if (silc_file_writefile_mode(filename, buf->data, buf->len, 0600)) {
1278 silc_buffer_clear(buf);
1279 silc_buffer_free(buf);
1280 silc_buffer_clear(enc);
1281 silc_buffer_free(enc);
1285 silc_buffer_clear(buf);
1286 silc_buffer_free(buf);
1287 silc_buffer_clear(enc);
1288 silc_buffer_free(enc);
1292 /* Saves private key into file. */
1294 bool silc_pkcs_save_private_key(const char *filename,
1295 SilcPrivateKey private_key,
1296 unsigned char *passphrase,
1297 SilcUInt32 passphrase_len,
1298 SilcUInt32 encoding)
1300 unsigned char *data;
1301 SilcUInt32 data_len;
1304 data = silc_pkcs_private_key_encode(private_key, &data_len);
1305 ret = silc_pkcs_save_private_key_internal(filename, data, data_len,
1306 passphrase, passphrase_len,
1308 memset(data, 0, data_len);
1313 /* Loads public key from file and allocates new public key. Returns TRUE
1314 if loading was successful. */
1316 bool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key,
1317 SilcUInt32 encoding)
1319 unsigned char *cp, *old, *data, byte;
1320 SilcUInt32 i, data_len, len;
1322 SILC_LOG_DEBUG(("Loading public key `%s' with %s encoding", filename,
1323 encoding == SILC_PKCS_FILE_PEM ? "Base64" :
1324 encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
1326 old = data = silc_file_readfile(filename, &data_len);
1330 /* Check start of file and remove header from the data. */
1331 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
1333 for (i = 0; i < len; i++) {
1336 if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
1337 memset(old, 0, data_len);
1344 /* Decode public key */
1346 len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1347 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1350 case SILC_PKCS_FILE_BIN:
1352 case SILC_PKCS_FILE_PEM:
1353 data = silc_pem_decode(data, len, &len);
1354 memset(old, 0, data_len);
1361 if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
1362 memset(old, 0, data_len);
1368 memset(old, 0, data_len);
1373 /* Load private key from file and allocates new private key. Returns TRUE
1374 if loading was successful. */
1376 bool silc_pkcs_load_private_key(const char *filename,
1377 SilcPrivateKey *private_key,
1378 unsigned char *passphrase,
1379 SilcUInt32 passphrase_len,
1380 SilcUInt32 encoding)
1385 SilcUInt32 blocklen;
1386 unsigned char tmp[32], keymat[64];
1387 unsigned char *cp, *old, *data, byte;
1388 SilcUInt32 i, data_len, len, magic, mac_len;
1390 SILC_LOG_DEBUG(("Loading private key `%s' with %s encoding", filename,
1391 encoding == SILC_PKCS_FILE_PEM ? "Base64" :
1392 encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
1394 old = data = silc_file_readfile(filename, &data_len);
1398 /* Check start of file and remove header from the data. */
1399 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
1401 for (i = 0; i < len; i++) {
1404 if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
1405 memset(old, 0, data_len);
1412 /* Decode private key */
1413 len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1414 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1417 case SILC_PKCS_FILE_BIN:
1419 case SILC_PKCS_FILE_PEM:
1420 data = silc_pem_decode(data, len, &len);
1422 memset(old, 0, data_len);
1429 memset(tmp, 0, sizeof(tmp));
1430 memset(keymat, 0, sizeof(keymat));
1432 /* Private key files without the specific magic number are assumed
1433 to be the old-style private keys that are not encrypted. */
1434 SILC_GET32_MSB(magic, data);
1435 if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
1436 SILC_LOG_DEBUG(("Private key does not have correct magic!"));
1438 /* Now decode the actual private key */
1439 if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1440 memset(old, 0, data_len);
1445 memset(old, 0, data_len);
1450 /* Allocate the AES cipher */
1451 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1452 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1453 memset(old, 0, data_len);
1457 blocklen = silc_cipher_get_block_len(aes);
1458 if (blocklen * 2 > sizeof(tmp)) {
1459 memset(old, 0, data_len);
1464 /* Allocate SHA1 hash */
1465 if (!silc_hash_alloc("sha1", &sha1)) {
1466 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1467 silc_cipher_free(aes);
1468 memset(old, 0, data_len);
1474 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1475 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1476 silc_hash_free(sha1);
1477 silc_cipher_free(aes);
1478 memset(old, 0, data_len);
1483 /* Derive the decryption key from the provided key material. The key
1484 is 256 bits length, and derived by taking hash of the data, then
1485 re-hashing the data and the previous digest, and using the first and
1486 second digest as the key. */
1487 silc_hash_init(sha1);
1488 silc_hash_update(sha1, passphrase, passphrase_len);
1489 silc_hash_final(sha1, keymat);
1490 silc_hash_init(sha1);
1491 silc_hash_update(sha1, passphrase, passphrase_len);
1492 silc_hash_update(sha1, keymat, 16);
1493 silc_hash_final(sha1, keymat + 16);
1495 /* Set the key to the cipher */
1496 silc_cipher_set_key(aes, keymat, 256);
1498 /* First, verify the MAC of the private key data */
1499 mac_len = silc_hmac_len(sha1hmac);
1500 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1501 silc_hmac_update(sha1hmac, data, len - mac_len);
1502 silc_hmac_final(sha1hmac, tmp, NULL);
1503 if (memcmp(tmp, data + (len - mac_len), mac_len)) {
1504 SILC_LOG_DEBUG(("Integrity check for private key failed"));
1505 memset(keymat, 0, sizeof(keymat));
1506 memset(tmp, 0, sizeof(tmp));
1507 silc_hmac_free(sha1hmac);
1508 silc_hash_free(sha1);
1509 silc_cipher_free(aes);
1510 memset(old, 0, data_len);
1517 /* Decrypt the private key buffer */
1518 silc_cipher_decrypt(aes, data, data, len - mac_len, NULL);
1519 SILC_GET32_MSB(i, data);
1521 SILC_LOG_DEBUG(("Bad private key length in buffer!"));
1522 memset(keymat, 0, sizeof(keymat));
1523 memset(tmp, 0, sizeof(tmp));
1524 silc_hmac_free(sha1hmac);
1525 silc_hash_free(sha1);
1526 silc_cipher_free(aes);
1527 memset(old, 0, data_len);
1535 memset(keymat, 0, sizeof(keymat));
1536 memset(tmp, 0, sizeof(tmp));
1537 silc_hmac_free(sha1hmac);
1538 silc_hash_free(sha1);
1539 silc_cipher_free(aes);
1541 /* Now decode the actual private key */
1542 if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1543 memset(old, 0, data_len);
1548 memset(old, 0, data_len);