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(public_key->len + 4);
691 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
693 silc_buffer_format(buf,
694 SILC_STR_UI_INT(public_key->len),
695 SILC_STR_UI_SHORT(strlen(public_key->name)),
696 SILC_STR_UI32_STRING(public_key->name),
697 SILC_STR_UI_SHORT(strlen(public_key->identifier)),
698 SILC_STR_UI32_STRING(public_key->identifier),
699 SILC_STR_UI_XNSTRING(public_key->pk,
703 *len = public_key->len + 4;
705 ret = silc_calloc(buf->len, sizeof(*ret));
706 memcpy(ret, buf->data, buf->len);
707 silc_buffer_free(buf);
712 /* Encodes SILC style public key. Returns the encoded data. */
715 silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
716 char *pkcs, char *identifier,
723 totlen = 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
724 buf = silc_buffer_alloc(totlen + 4);
725 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
727 silc_buffer_format(buf,
728 SILC_STR_UI_INT(totlen),
729 SILC_STR_UI_SHORT(strlen(pkcs)),
730 SILC_STR_UI32_STRING(pkcs),
731 SILC_STR_UI_SHORT(strlen(identifier)),
732 SILC_STR_UI32_STRING(identifier),
733 SILC_STR_UI_XNSTRING(pk, pk_len),
738 ret = silc_calloc(buf->len, sizeof(*ret));
739 memcpy(ret, buf->data, buf->len);
740 silc_buffer_free(buf);
745 /* Decodes SILC style public key. Returns TRUE if the decoding was
746 successful. Allocates new public key as well. */
748 bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
749 SilcPublicKey *public_key)
753 SilcUInt16 pkcs_len, identifier_len;
754 SilcUInt32 totlen, key_len;
755 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
758 buf = silc_buffer_alloc(data_len);
759 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
760 silc_buffer_put(buf, data, data_len);
763 ret = silc_buffer_unformat(buf,
764 SILC_STR_UI_INT(&totlen),
767 silc_buffer_free(buf);
771 #if 1 /* Backwards support, remove! */
772 if (totlen == data_len)
776 if (totlen + 4 != data_len) {
777 silc_buffer_free(buf);
781 /* Get algorithm name and identifier */
782 silc_buffer_pull(buf, 4);
784 silc_buffer_unformat(buf,
785 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
786 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
791 if (pkcs_len < 1 || identifier_len < 3 ||
792 pkcs_len + identifier_len > totlen)
795 /* See if we support this algorithm (check only if PKCS are registered) */
796 if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
797 SILC_LOG_DEBUG(("Unknown PKCS %s", pkcs_name));
801 /* Protocol says that at least UN and HN must be provided as identifier,
803 if (!strstr(ident, "UN=") && !strstr(ident, "HN=")) {
804 SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
809 /* Get key data. We assume that rest of the buffer is key data. */
810 silc_buffer_pull(buf, 2 + pkcs_len + 2 + identifier_len);
812 ret = silc_buffer_unformat(buf,
813 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
818 /* Try to set the key. If this fails the key must be malformed. This
819 code assumes that the PKCS routine checks the format of the key.
820 (check only if PKCS are registered) */
821 if (SILC_PKCS_LIST) {
822 silc_pkcs_alloc(pkcs_name, &alg);
823 if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
829 *public_key = silc_calloc(1, sizeof(**public_key));
830 (*public_key)->len = totlen;
831 (*public_key)->name = pkcs_name;
832 (*public_key)->identifier = ident;
833 (*public_key)->pk = key_data;
834 (*public_key)->pk_len = key_len;
835 (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
838 silc_buffer_free(buf);
843 silc_free(pkcs_name);
848 silc_buffer_free(buf);
852 /* Encodes Public Key Payload for transmitting public keys and certificates. */
854 SilcBuffer silc_pkcs_public_key_payload_encode(SilcPublicKey public_key)
863 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
867 buffer = silc_buffer_alloc_size(4 + pk_len);
873 silc_buffer_format(buffer,
874 SILC_STR_UI_SHORT(pk_len),
875 SILC_STR_UI_SHORT(public_key->pk_type),
876 SILC_STR_UI_XNSTRING(pk, pk_len),
883 /* Decode Public Key Payload and decodes the public key inside it to
886 bool silc_pkcs_public_key_payload_decode(unsigned char *data,
888 SilcPublicKey *public_key)
890 SilcBufferStruct buf;
891 SilcUInt16 pk_len, pk_type;
899 /* XXX 1.1 version support. Check whether the data is actually raw
900 public key and attempt to decode. Remove this later! */
901 if (silc_pkcs_public_key_decode(data, data_len, public_key)) {
902 (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
907 silc_buffer_set(&buf, data, data_len);
908 ret = silc_buffer_unformat(&buf,
909 SILC_STR_UI_SHORT(&pk_len),
910 SILC_STR_UI_SHORT(&pk_type),
912 if (ret < 0 || pk_len > data_len - 4)
915 /* For now we support only SILC public keys */
916 if (pk_type != SILC_SKE_PK_TYPE_SILC)
919 silc_buffer_pull(&buf, 4);
920 ret = silc_buffer_unformat(&buf,
921 SILC_STR_UI_XNSTRING(&pk, pk_len),
923 silc_buffer_push(&buf, 4);
927 if (!silc_pkcs_public_key_decode(pk, pk_len, public_key))
929 (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
934 /* Compares two public keys and returns TRUE if they are same key, and
935 FALSE if they are not same. */
937 bool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
942 if (key1->len == key2->len &&
943 key1->name && key2->name && key1->identifier && key2->identifier &&
944 !strcmp(key1->name, key2->name) &&
945 !strcmp(key1->identifier, key2->identifier) &&
946 !memcmp(key1->pk, key2->pk, key1->pk_len) &&
947 key1->pk_len == key2->pk_len)
953 /* Copies the public key indicated by `public_key' and returns new allocated
954 public key which is indentical to the `public_key'. */
956 SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
958 SilcPublicKey key = silc_calloc(1, sizeof(*key));
962 key->len = public_key->len;
963 key->name = silc_memdup(public_key->name, strlen(public_key->name));
964 key->identifier = silc_memdup(public_key->identifier,
965 strlen(public_key->identifier));
966 key->pk = silc_memdup(public_key->pk, public_key->pk_len);
967 key->pk_len = public_key->pk_len;
968 key->pk_type = public_key->pk_type;
973 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
976 silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
982 totlen = 2 + strlen(private_key->name) + private_key->prv_len;
983 buf = silc_buffer_alloc(totlen);
984 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
986 silc_buffer_format(buf,
987 SILC_STR_UI_SHORT(strlen(private_key->name)),
988 SILC_STR_UI32_STRING(private_key->name),
989 SILC_STR_UI_XNSTRING(private_key->prv,
990 private_key->prv_len),
995 ret = silc_calloc(buf->len, sizeof(*ret));
996 memcpy(ret, buf->data, buf->len);
997 silc_buffer_clear(buf);
998 silc_buffer_free(buf);
1003 /* Encodes SILC private key. Returns the encoded data. */
1006 silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
1007 char *pkcs, SilcUInt32 *len)
1013 totlen = 2 + strlen(pkcs) + prv_len;
1014 buf = silc_buffer_alloc(totlen);
1015 silc_buffer_pull_tail(buf, totlen);
1017 silc_buffer_format(buf,
1018 SILC_STR_UI_SHORT(strlen(pkcs)),
1019 SILC_STR_UI32_STRING(pkcs),
1020 SILC_STR_UI_XNSTRING(prv, prv_len),
1025 ret = silc_calloc(buf->len, sizeof(*ret));
1026 memcpy(ret, buf->data, buf->len);
1027 silc_buffer_clear(buf);
1028 silc_buffer_free(buf);
1033 /* Decodes SILC style private key. Returns TRUE if the decoding was
1034 successful. Allocates new private key as well. */
1036 bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
1037 SilcPrivateKey *private_key)
1041 SilcUInt16 pkcs_len;
1043 unsigned char *pkcs_name = NULL, *key_data = NULL;
1046 buf = silc_buffer_alloc(data_len);
1047 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1048 silc_buffer_put(buf, data, data_len);
1050 /* Get algorithm name and identifier */
1052 silc_buffer_unformat(buf,
1053 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
1056 SILC_LOG_DEBUG(("Cannot decode private key buffer"));
1060 if (pkcs_len < 1 || pkcs_len > buf->truelen) {
1061 SILC_LOG_DEBUG(("Malformed private key buffer"));
1065 /* See if we support this algorithm (check only if PKCS are registered). */
1066 if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
1067 SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
1071 /* Get key data. We assume that rest of the buffer is key data. */
1072 silc_buffer_pull(buf, 2 + pkcs_len);
1074 ret = silc_buffer_unformat(buf,
1075 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
1080 /* Try to set the key. If this fails the key must be malformed. This
1081 code assumes that the PKCS routine checks the format of the key.
1082 (check only if PKCS are registered) */
1083 if (SILC_PKCS_LIST) {
1084 silc_pkcs_alloc(pkcs_name, &alg);
1085 if (!alg->pkcs->set_private_key(alg->context, key_data, key_len)) {
1086 SILC_LOG_DEBUG(("Could not set private key data"));
1089 silc_pkcs_free(alg);
1093 *private_key = silc_calloc(1, sizeof(**private_key));
1094 (*private_key)->name = pkcs_name;
1095 (*private_key)->prv = key_data;
1096 (*private_key)->prv_len = key_len;
1099 silc_buffer_clear(buf);
1100 silc_buffer_free(buf);
1105 silc_free(pkcs_name);
1107 silc_free(key_data);
1108 silc_buffer_clear(buf);
1109 silc_buffer_free(buf);
1113 /* Internal routine to save public key */
1115 static bool silc_pkcs_save_public_key_internal(const char *filename,
1116 unsigned char *data,
1117 SilcUInt32 data_len,
1118 SilcUInt32 encoding)
1124 case SILC_PKCS_FILE_BIN:
1126 case SILC_PKCS_FILE_PEM:
1127 data = silc_pem_encode_file(data, data_len);
1128 data_len = strlen(data);
1132 len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1133 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1134 buf = silc_buffer_alloc(len);
1135 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1137 silc_buffer_format(buf,
1138 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
1139 SILC_STR_UI_XNSTRING(data, data_len),
1140 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
1143 /* Save into file */
1144 if (silc_file_writefile(filename, buf->data, buf->len)) {
1145 silc_buffer_free(buf);
1149 silc_buffer_free(buf);
1153 /* Saves public key into file */
1155 bool silc_pkcs_save_public_key(const char *filename, SilcPublicKey public_key,
1156 SilcUInt32 encoding)
1158 unsigned char *data;
1159 SilcUInt32 data_len;
1162 data = silc_pkcs_public_key_encode(public_key, &data_len);
1163 ret = silc_pkcs_save_public_key_internal(filename, data, data_len,
1169 /* Saves public key into file */
1171 bool silc_pkcs_save_public_key_data(const char *filename, unsigned char *data,
1172 SilcUInt32 data_len, SilcUInt32 encoding)
1174 return silc_pkcs_save_public_key_internal(filename, data, data_len,
1178 #define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
1180 /* Internal routine to save private key. */
1182 static bool silc_pkcs_save_private_key_internal(const char *filename,
1183 unsigned char *data,
1184 SilcUInt32 data_len,
1187 SilcUInt32 encoding)
1192 SilcBuffer buf, enc;
1193 SilcUInt32 len, blocklen, padlen;
1194 unsigned char tmp[32], keymat[64];
1197 memset(tmp, 0, sizeof(tmp));
1198 memset(keymat, 0, sizeof(keymat));
1200 /* Allocate the AES cipher */
1201 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1202 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1205 blocklen = silc_cipher_get_block_len(aes);
1206 if (blocklen * 2 > sizeof(tmp))
1209 /* Allocate SHA1 hash */
1210 if (!silc_hash_alloc("sha1", &sha1)) {
1211 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1212 silc_cipher_free(aes);
1217 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1218 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1219 silc_hash_free(sha1);
1220 silc_cipher_free(aes);
1224 /* Derive the encryption key from the provided key material. The key
1225 is 256 bits length, and derived by taking hash of the data, then
1226 re-hashing the data and the previous digest, and using the first and
1227 second digest as the key. */
1228 silc_hash_init(sha1);
1229 silc_hash_update(sha1, key, key_len);
1230 silc_hash_final(sha1, keymat);
1231 silc_hash_init(sha1);
1232 silc_hash_update(sha1, key, key_len);
1233 silc_hash_update(sha1, keymat, 16);
1234 silc_hash_final(sha1, keymat + 16);
1236 /* Set the key to the cipher */
1237 silc_cipher_set_key(aes, keymat, 256);
1239 /* Encode the buffer to be encrypted. Add padding to it too, at least
1240 block size of the cipher. */
1242 /* Allocate buffer for encryption */
1243 len = silc_hmac_len(sha1hmac);
1244 padlen = 16 + (16 - ((data_len + 4) % blocklen));
1245 enc = silc_buffer_alloc_size(4 + 4 + data_len + padlen + len);
1247 silc_hmac_free(sha1hmac);
1248 silc_hash_free(sha1);
1249 silc_cipher_free(aes);
1253 /* Generate padding */
1254 for (i = 0; i < padlen; i++)
1255 tmp[i] = silc_rng_global_get_byte_fast();
1257 /* Put magic number */
1258 SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
1259 silc_buffer_pull(enc, 4);
1261 /* Encode the buffer */
1262 silc_buffer_format(enc,
1263 SILC_STR_UI_INT(data_len),
1264 SILC_STR_UI_XNSTRING(data, data_len),
1265 SILC_STR_UI_XNSTRING(tmp, padlen),
1269 silc_cipher_encrypt(aes, enc->data, enc->data, enc->len - len,
1270 silc_cipher_get_iv(aes));
1272 silc_buffer_push(enc, 4);
1274 /* Compute HMAC over the encrypted data and append the MAC to data.
1275 The key is the first digest of the original key material. */
1276 data_len = enc->len - len;
1277 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1278 silc_hmac_update(sha1hmac, enc->data, data_len);
1279 silc_buffer_pull(enc, data_len);
1280 silc_hmac_final(sha1hmac, enc->data, NULL);
1281 silc_buffer_push(enc, data_len);
1284 memset(keymat, 0, sizeof(keymat));
1285 memset(tmp, 0, sizeof(tmp));
1286 silc_hmac_free(sha1hmac);
1287 silc_hash_free(sha1);
1288 silc_cipher_free(aes);
1291 data_len = enc->len;
1294 case SILC_PKCS_FILE_BIN:
1296 case SILC_PKCS_FILE_PEM:
1297 data = silc_pem_encode_file(data, data_len);
1298 data_len = strlen(data);
1302 /* Encode the data and save to file */
1303 len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1304 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1305 buf = silc_buffer_alloc_size(len);
1306 silc_buffer_format(buf,
1307 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
1308 SILC_STR_UI_XNSTRING(data, data_len),
1309 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
1312 /* Save into a file */
1313 if (silc_file_writefile_mode(filename, buf->data, buf->len, 0600)) {
1314 silc_buffer_clear(buf);
1315 silc_buffer_free(buf);
1316 silc_buffer_clear(enc);
1317 silc_buffer_free(enc);
1321 silc_buffer_clear(buf);
1322 silc_buffer_free(buf);
1323 silc_buffer_clear(enc);
1324 silc_buffer_free(enc);
1328 /* Saves private key into file. */
1330 bool silc_pkcs_save_private_key(const char *filename,
1331 SilcPrivateKey private_key,
1332 unsigned char *passphrase,
1333 SilcUInt32 passphrase_len,
1334 SilcUInt32 encoding)
1336 unsigned char *data;
1337 SilcUInt32 data_len;
1340 data = silc_pkcs_private_key_encode(private_key, &data_len);
1341 ret = silc_pkcs_save_private_key_internal(filename, data, data_len,
1342 passphrase, passphrase_len,
1344 memset(data, 0, data_len);
1349 /* Loads public key from file and allocates new public key. Returns TRUE
1350 if loading was successful. */
1352 bool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key,
1353 SilcUInt32 encoding)
1355 unsigned char *cp, *old, *data, byte;
1356 SilcUInt32 i, data_len, len;
1358 SILC_LOG_DEBUG(("Loading public key `%s' with %s encoding", filename,
1359 encoding == SILC_PKCS_FILE_PEM ? "Base64" :
1360 encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
1362 old = data = silc_file_readfile(filename, &data_len);
1366 /* Check start of file and remove header from the data. */
1367 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
1369 for (i = 0; i < len; i++) {
1372 if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
1373 memset(old, 0, data_len);
1380 /* Decode public key */
1382 len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1383 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1386 case SILC_PKCS_FILE_BIN:
1388 case SILC_PKCS_FILE_PEM:
1389 data = silc_pem_decode(data, len, &len);
1390 memset(old, 0, data_len);
1397 if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
1398 memset(old, 0, data_len);
1404 memset(old, 0, data_len);
1409 #if 1 /* Old MD5 routine for private key loading, remove later! */
1413 unsigned char in[64];
1415 static void MD5Init(struct MD5Context *ctx)
1417 ctx->buf[0] = 0x67452301;
1418 ctx->buf[1] = 0xefcdab89;
1419 ctx->buf[2] = 0x98badcfe;
1420 ctx->buf[3] = 0x10325476;
1421 ctx->bits[0] = ctx->bits[1] = 0;
1424 MD5Transform(SilcUInt32 buf[4], const unsigned char kbuf[64]);
1426 MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
1431 if ((ctx->bits[0] = t + ((SilcUInt32)len << 3)) < t)
1432 ctx->bits[1]++; /* Carry from low to high */
1433 ctx->bits[1] += (SilcUInt32)len >> 29;
1434 t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
1436 unsigned char *p = (unsigned char *)ctx->in + t;
1440 memcpy(p, buf, len);
1444 MD5Transform(ctx->buf, ctx->in);
1447 } while (len >= 64) {
1448 memcpy(ctx->in, buf, 64);
1449 MD5Transform(ctx->buf, ctx->in);
1453 memcpy(ctx->in, buf, len);
1456 static void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
1460 count = (ctx->bits[0] >> 3) & 0x3F;
1461 p = ctx->in + count;
1463 count = 64 - 1 - count;
1465 memset(p, 0, count);
1466 MD5Transform(ctx->buf, ctx->in);
1467 memset(ctx->in, 0, 56);
1469 memset(p, 0, count-8);
1471 ((SilcUInt32 *)ctx->in)[ 14 ] = ctx->bits[0];
1472 ((SilcUInt32 *)ctx->in)[ 15 ] = ctx->bits[1];
1473 MD5Transform(ctx->buf, ctx->in);
1474 memcpy(digest, ctx->buf, 16);
1475 memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
1477 #define F1(x, y, z) (z ^ (x & (y ^ z)))
1478 #define F2(x, y, z) F1(z, x, y)
1479 #define F3(x, y, z) (x ^ y ^ z)
1480 #define F4(x, y, z) (y ^ (x | ~z))
1481 #define MD5STEP(f, w, x, y, z, data, s) \
1482 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
1484 MD5Transform(SilcUInt32 buf[4], const unsigned char kbuf[64])
1486 register SilcUInt32 a, b, c, d, i;
1488 for (i = 0; i < 16; i++)
1489 SILC_GET32_MSB(in[i], kbuf + 4 * i);
1490 a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3];
1491 MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
1492 MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
1493 MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
1494 MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
1495 MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
1496 MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
1497 MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
1498 MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
1499 MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
1500 MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
1501 MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
1502 MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
1503 MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
1504 MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
1505 MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
1506 MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
1507 MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
1508 MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
1509 MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
1510 MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
1511 MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
1512 MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
1513 MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
1514 MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
1515 MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
1516 MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
1517 MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
1518 MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
1519 MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
1520 MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
1521 MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
1522 MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
1523 MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
1524 MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
1525 MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
1526 MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
1527 MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
1528 MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
1529 MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
1530 MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
1531 MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
1532 MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
1533 MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
1534 MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
1535 MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
1536 MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
1537 MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
1538 MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
1539 MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
1540 MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
1541 MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
1542 MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
1543 MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
1544 MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
1545 MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
1546 MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
1547 MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
1548 MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
1549 MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
1550 MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
1551 MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
1552 MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
1553 MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
1554 MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
1555 buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d;
1559 /* Load private key from file and allocates new private key. Returns TRUE
1560 if loading was successful. */
1562 bool silc_pkcs_load_private_key(const char *filename,
1563 SilcPrivateKey *private_key,
1564 unsigned char *passphrase,
1565 SilcUInt32 passphrase_len,
1566 SilcUInt32 encoding)
1571 SilcUInt32 blocklen;
1572 unsigned char tmp[32], keymat[64];
1573 unsigned char *cp, *old, *data, byte;
1574 SilcUInt32 i, data_len, len, magic, mac_len;
1578 struct MD5Context md5;
1579 bool oldsupport = FALSE;
1583 SILC_LOG_DEBUG(("Loading private key `%s' with %s encoding", filename,
1584 encoding == SILC_PKCS_FILE_PEM ? "Base64" :
1585 encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
1587 old = data = silc_file_readfile(filename, &data_len);
1591 /* Check start of file and remove header from the data. */
1592 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
1594 for (i = 0; i < len; i++) {
1597 if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
1598 memset(old, 0, data_len);
1605 /* Decode private key */
1606 len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1607 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1610 case SILC_PKCS_FILE_BIN:
1612 case SILC_PKCS_FILE_PEM:
1613 data = silc_pem_decode(data, len, &len);
1615 memset(old, 0, data_len);
1622 memset(tmp, 0, sizeof(tmp));
1623 memset(keymat, 0, sizeof(keymat));
1625 /* Private key files without the specific magic number are assumed
1626 to be the old-style private keys that are not encrypted. */
1627 SILC_GET32_MSB(magic, data);
1628 if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
1629 SILC_LOG_DEBUG(("Private key does not have correct magic!"));
1631 /* Now decode the actual private key */
1632 if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1633 memset(old, 0, data_len);
1638 memset(old, 0, data_len);
1643 /* Allocate the AES cipher */
1644 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1645 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1646 memset(old, 0, data_len);
1650 blocklen = silc_cipher_get_block_len(aes);
1651 if (blocklen * 2 > sizeof(tmp)) {
1652 memset(old, 0, data_len);
1657 /* Allocate SHA1 hash */
1658 if (!silc_hash_alloc("sha1", &sha1)) {
1659 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1660 silc_cipher_free(aes);
1661 memset(old, 0, data_len);
1667 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1668 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1669 silc_hash_free(sha1);
1670 silc_cipher_free(aes);
1671 memset(old, 0, data_len);
1676 /* Derive the decryption key from the provided key material. The key
1677 is 256 bits length, and derived by taking hash of the data, then
1678 re-hashing the data and the previous digest, and using the first and
1679 second digest as the key. */
1680 silc_hash_init(sha1);
1681 silc_hash_update(sha1, passphrase, passphrase_len);
1682 silc_hash_final(sha1, keymat);
1683 silc_hash_init(sha1);
1684 silc_hash_update(sha1, passphrase, passphrase_len);
1685 silc_hash_update(sha1, keymat, 16);
1686 silc_hash_final(sha1, keymat + 16);
1693 MD5Update(&md5, passphrase, passphrase_len);
1694 MD5Final(keymat, &md5);
1696 MD5Update(&md5, passphrase, passphrase_len);
1697 MD5Update(&md5, keymat, 16);
1698 MD5Final(keymat + 16, &md5);
1702 /* Set the key to the cipher */
1703 silc_cipher_set_key(aes, keymat, 256);
1705 /* First, verify the MAC of the private key data */
1706 mac_len = silc_hmac_len(sha1hmac);
1707 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1708 silc_hmac_update(sha1hmac, data, len - mac_len);
1709 silc_hmac_final(sha1hmac, tmp, NULL);
1710 if (memcmp(tmp, data + (len - mac_len), mac_len)) {
1719 SILC_LOG_DEBUG(("Integrity check for private key failed"));
1720 memset(keymat, 0, sizeof(keymat));
1721 memset(tmp, 0, sizeof(tmp));
1722 silc_hmac_free(sha1hmac);
1723 silc_hash_free(sha1);
1724 silc_cipher_free(aes);
1725 memset(old, 0, data_len);
1734 oldlen = len - mac_len;
1737 /* Decrypt the private key buffer */
1738 silc_cipher_decrypt(aes, data, data, len - mac_len, NULL);
1739 SILC_GET32_MSB(i, data);
1741 SILC_LOG_DEBUG(("Bad private key length in buffer!"));
1742 memset(keymat, 0, sizeof(keymat));
1743 memset(tmp, 0, sizeof(tmp));
1744 silc_hmac_free(sha1hmac);
1745 silc_hash_free(sha1);
1746 silc_cipher_free(aes);
1747 memset(old, 0, data_len);
1755 memset(keymat, 0, sizeof(keymat));
1756 memset(tmp, 0, sizeof(tmp));
1757 silc_hmac_free(sha1hmac);
1758 silc_hash_free(sha1);
1759 silc_cipher_free(aes);
1761 /* Now decode the actual private key */
1762 if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1763 memset(old, 0, data_len);
1770 if (oldsupport || (oldlen & 15))
1771 silc_pkcs_save_private_key((char *)filename, *private_key,
1772 passphrase, passphrase_len, encoding);
1775 memset(old, 0, data_len);