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 memcpy(public_key->pk, pk, pk_len);
625 if (!silc_utf8_valid(identifier, strlen(identifier))) {
626 int len = silc_utf8_encoded_len(identifier, strlen(identifier), 0);
627 tmp = silc_calloc(len + 1, sizeof(*tmp));
628 silc_utf8_encode(identifier, strlen(identifier), 0, tmp, len);
632 public_key->identifier = strdup(identifier);
633 public_key->len = 4 + 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
639 /* Free's public key */
641 void silc_pkcs_public_key_free(SilcPublicKey public_key)
644 silc_free(public_key->name);
645 silc_free(public_key->identifier);
646 silc_free(public_key->pk);
647 silc_free(public_key);
651 /* Allocates SILC private key formed from sent arguments. All data is
654 SilcPrivateKey silc_pkcs_private_key_alloc(const char *name,
655 const unsigned char *prv,
658 SilcPrivateKey private_key;
660 private_key = silc_calloc(1, sizeof(*private_key));
661 private_key->name = strdup(name);
662 private_key->prv_len = prv_len;
663 private_key->prv = silc_calloc(prv_len, sizeof(*private_key->prv));
664 memcpy(private_key->prv, prv, prv_len);
669 /* Free's private key */
671 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
674 silc_free(private_key->name);
675 silc_free(private_key->prv);
676 silc_free(private_key);
680 /* Encodes SILC style public key from SilcPublicKey. Returns the encoded
684 silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len)
689 buf = silc_buffer_alloc(public_key->len);
690 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
692 silc_buffer_format(buf,
693 SILC_STR_UI_INT(public_key->len),
694 SILC_STR_UI_SHORT(strlen(public_key->name)),
695 SILC_STR_UI32_STRING(public_key->name),
696 SILC_STR_UI_SHORT(strlen(public_key->identifier)),
697 SILC_STR_UI32_STRING(public_key->identifier),
698 SILC_STR_UI_XNSTRING(public_key->pk,
702 *len = public_key->len;
704 ret = silc_calloc(buf->len, sizeof(*ret));
705 memcpy(ret, buf->data, buf->len);
706 silc_buffer_free(buf);
711 /* Encodes SILC style public key. Returns the encoded data. */
714 silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
715 char *pkcs, char *identifier,
722 totlen = 4 + 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
723 buf = silc_buffer_alloc(totlen);
724 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
726 silc_buffer_format(buf,
727 SILC_STR_UI_INT(totlen),
728 SILC_STR_UI_SHORT(strlen(pkcs)),
729 SILC_STR_UI32_STRING(pkcs),
730 SILC_STR_UI_SHORT(strlen(identifier)),
731 SILC_STR_UI32_STRING(identifier),
732 SILC_STR_UI_XNSTRING(pk, pk_len),
737 ret = silc_calloc(buf->len, sizeof(*ret));
738 memcpy(ret, buf->data, buf->len);
739 silc_buffer_free(buf);
744 /* Decodes SILC style public key. Returns TRUE if the decoding was
745 successful. Allocates new public key as well. */
747 bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
748 SilcPublicKey *public_key)
752 SilcUInt16 pkcs_len, identifier_len;
753 SilcUInt32 totlen, key_len;
754 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
757 buf = silc_buffer_alloc(data_len);
758 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
759 silc_buffer_put(buf, data, data_len);
762 ret = silc_buffer_unformat(buf,
763 SILC_STR_UI_INT(&totlen),
766 silc_buffer_free(buf);
770 if (totlen != data_len) {
771 silc_buffer_free(buf);
775 /* Get algorithm name and identifier */
776 silc_buffer_pull(buf, 4);
778 silc_buffer_unformat(buf,
779 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
780 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
785 if (pkcs_len < 1 || identifier_len < 3 ||
786 pkcs_len + identifier_len > totlen)
789 /* See if we support this algorithm (check only if PKCS are registered) */
790 if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
791 SILC_LOG_DEBUG(("Unknown PKCS %s", pkcs_name));
795 /* Protocol says that at least UN and HN must be provided as identifier,
797 if (!strstr(ident, "UN=") && !strstr(ident, "HN=")) {
798 SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
803 /* Get key data. We assume that rest of the buffer is key data. */
804 silc_buffer_pull(buf, 2 + pkcs_len + 2 + identifier_len);
806 ret = silc_buffer_unformat(buf,
807 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
812 /* Try to set the key. If this fails the key must be malformed. This
813 code assumes that the PKCS routine checks the format of the key.
814 (check only if PKCS are registered) */
815 if (SILC_PKCS_LIST) {
816 silc_pkcs_alloc(pkcs_name, &alg);
817 if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
823 *public_key = silc_calloc(1, sizeof(**public_key));
824 (*public_key)->len = totlen;
825 (*public_key)->name = pkcs_name;
826 (*public_key)->identifier = ident;
827 (*public_key)->pk = key_data;
828 (*public_key)->pk_len = key_len;
831 silc_buffer_free(buf);
836 silc_free(pkcs_name);
841 silc_buffer_free(buf);
845 /* Compares two public keys and returns TRUE if they are same key, and
846 FALSE if they are not same. */
848 bool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
853 if (key1->len == key2->len &&
854 key1->name && key2->name && key1->identifier && key2->identifier &&
855 !strcmp(key1->name, key2->name) &&
856 !strcmp(key1->identifier, key2->identifier) &&
857 !memcmp(key1->pk, key2->pk, key1->pk_len) &&
858 key1->pk_len == key2->pk_len)
864 /* Copies the public key indicated by `public_key' and returns new allocated
865 public key which is indentical to the `public_key'. */
867 SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
869 SilcPublicKey key = silc_calloc(1, sizeof(*key));
873 key->len = public_key->len;
874 key->name = silc_memdup(public_key->name, strlen(public_key->name));
875 key->identifier = silc_memdup(public_key->identifier,
876 strlen(public_key->identifier));
877 key->pk = silc_memdup(public_key->pk, public_key->pk_len);
878 key->pk_len = public_key->pk_len;
883 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
886 silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
892 totlen = 2 + strlen(private_key->name) + private_key->prv_len;
893 buf = silc_buffer_alloc(totlen);
894 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
896 silc_buffer_format(buf,
897 SILC_STR_UI_SHORT(strlen(private_key->name)),
898 SILC_STR_UI32_STRING(private_key->name),
899 SILC_STR_UI_XNSTRING(private_key->prv,
900 private_key->prv_len),
905 ret = silc_calloc(buf->len, sizeof(*ret));
906 memcpy(ret, buf->data, buf->len);
907 silc_buffer_clear(buf);
908 silc_buffer_free(buf);
913 /* Encodes SILC private key. Returns the encoded data. */
916 silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
917 char *pkcs, SilcUInt32 *len)
923 totlen = 2 + strlen(pkcs) + prv_len;
924 buf = silc_buffer_alloc(totlen);
925 silc_buffer_pull_tail(buf, totlen);
927 silc_buffer_format(buf,
928 SILC_STR_UI_SHORT(strlen(pkcs)),
929 SILC_STR_UI32_STRING(pkcs),
930 SILC_STR_UI_XNSTRING(prv, prv_len),
935 ret = silc_calloc(buf->len, sizeof(*ret));
936 memcpy(ret, buf->data, buf->len);
937 silc_buffer_clear(buf);
938 silc_buffer_free(buf);
943 /* Decodes SILC style private key. Returns TRUE if the decoding was
944 successful. Allocates new private key as well. */
946 bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
947 SilcPrivateKey *private_key)
953 unsigned char *pkcs_name = NULL, *key_data = NULL;
956 buf = silc_buffer_alloc(data_len);
957 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
958 silc_buffer_put(buf, data, data_len);
960 /* Get algorithm name and identifier */
962 silc_buffer_unformat(buf,
963 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
966 SILC_LOG_DEBUG(("Cannot decode private key buffer"));
970 if (pkcs_len < 1 || pkcs_len > buf->truelen) {
971 SILC_LOG_DEBUG(("Malformed private key buffer"));
975 /* See if we support this algorithm (check only if PKCS are registered). */
976 if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
977 SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
981 /* Get key data. We assume that rest of the buffer is key data. */
982 silc_buffer_pull(buf, 2 + pkcs_len);
984 ret = silc_buffer_unformat(buf,
985 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
990 /* Try to set the key. If this fails the key must be malformed. This
991 code assumes that the PKCS routine checks the format of the key.
992 (check only if PKCS are registered) */
993 if (SILC_PKCS_LIST) {
994 silc_pkcs_alloc(pkcs_name, &alg);
995 if (!alg->pkcs->set_private_key(alg->context, key_data, key_len)) {
996 SILC_LOG_DEBUG(("Could not set private key data"));
1003 *private_key = silc_calloc(1, sizeof(**private_key));
1004 (*private_key)->name = pkcs_name;
1005 (*private_key)->prv = key_data;
1006 (*private_key)->prv_len = key_len;
1009 silc_buffer_clear(buf);
1010 silc_buffer_free(buf);
1015 silc_free(pkcs_name);
1017 silc_free(key_data);
1018 silc_buffer_clear(buf);
1019 silc_buffer_free(buf);
1023 /* Internal routine to save public key */
1025 static bool silc_pkcs_save_public_key_internal(char *filename,
1026 unsigned char *data,
1027 SilcUInt32 data_len,
1028 SilcUInt32 encoding)
1034 case SILC_PKCS_FILE_BIN:
1036 case SILC_PKCS_FILE_PEM:
1037 data = silc_pem_encode_file(data, data_len);
1038 data_len = strlen(data);
1042 len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1043 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1044 buf = silc_buffer_alloc(len);
1045 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
1047 silc_buffer_format(buf,
1048 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
1049 SILC_STR_UI_XNSTRING(data, data_len),
1050 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
1053 /* Save into file */
1054 if (silc_file_writefile(filename, buf->data, buf->len)) {
1055 silc_buffer_free(buf);
1059 silc_buffer_free(buf);
1063 /* Saves public key into file */
1065 bool silc_pkcs_save_public_key(char *filename, SilcPublicKey public_key,
1066 SilcUInt32 encoding)
1068 unsigned char *data;
1069 SilcUInt32 data_len;
1072 data = silc_pkcs_public_key_encode(public_key, &data_len);
1073 ret = silc_pkcs_save_public_key_internal(filename, data, data_len,
1079 /* Saves public key into file */
1081 bool silc_pkcs_save_public_key_data(char *filename, unsigned char *data,
1082 SilcUInt32 data_len,
1083 SilcUInt32 encoding)
1085 return silc_pkcs_save_public_key_internal(filename, data, data_len,
1089 #define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
1091 /* Internal routine to save private key. */
1093 static bool silc_pkcs_save_private_key_internal(char *filename,
1094 unsigned char *data,
1095 SilcUInt32 data_len,
1098 SilcUInt32 encoding)
1103 SilcBuffer buf, enc;
1104 SilcUInt32 len, blocklen;
1105 unsigned char tmp[32], keymat[32];
1108 memset(tmp, 0, sizeof(tmp));
1109 memset(keymat, 0, sizeof(keymat));
1111 /* Allocate the AES cipher */
1112 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1113 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1116 blocklen = silc_cipher_get_block_len(aes);
1117 if (blocklen * 2 > sizeof(tmp))
1120 /* Allocate MD5 hash */
1121 if (!silc_hash_alloc("md5", &md5)) {
1122 SILC_LOG_ERROR(("Could not allocate MD5 hash, probably not registered"));
1123 silc_cipher_free(aes);
1128 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1129 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1130 silc_hash_free(md5);
1131 silc_cipher_free(aes);
1135 /* Derive the encryption key from the provided key material. The key
1136 is 256 bits length, and derived by taking hash of the data, then
1137 re-hashing the data and the previous digest, and using the first and
1138 second digest as the key. */
1139 silc_hash_init(md5);
1140 silc_hash_update(md5, key, key_len);
1141 silc_hash_final(md5, keymat);
1142 silc_hash_init(md5);
1143 silc_hash_update(md5, key, key_len);
1144 silc_hash_update(md5, keymat, 16);
1145 silc_hash_final(md5, keymat + 16);
1147 /* Set the key to the cipher */
1148 silc_cipher_set_key(aes, keymat, sizeof(keymat) * 8);
1150 /* Encode the buffer to be encrypted. Add padding to it too, at least
1151 block size of the cipher. */
1153 /* Allocate buffer for encryption */
1154 len = silc_hmac_len(sha1hmac);
1155 enc = silc_buffer_alloc_size(data_len + 4 + 4 +
1156 (blocklen + (data_len % blocklen)) + len);
1158 silc_hmac_free(sha1hmac);
1159 silc_hash_free(md5);
1160 silc_cipher_free(aes);
1164 /* Generate padding */
1165 for (i = 0; i < blocklen + (data_len % blocklen); i++)
1166 tmp[i] = silc_rng_global_get_byte_fast();
1168 /* Put magic number */
1169 SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
1170 silc_buffer_pull(enc, 4);
1172 /* Encode the buffer */
1173 silc_buffer_format(enc,
1174 SILC_STR_UI_INT(data_len),
1175 SILC_STR_UI_XNSTRING(data, data_len),
1176 SILC_STR_UI_XNSTRING(tmp, blocklen + (data_len %
1181 silc_cipher_encrypt(aes, enc->data, enc->data, enc->len - len,
1182 silc_cipher_get_iv(aes));
1184 silc_buffer_push(enc, 4);
1186 /* Compute HMAC over the encrypted data and append the MAC to data.
1187 The key is the first digest of the original key material. */
1188 data_len = enc->len - len;
1189 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1190 silc_hmac_update(sha1hmac, enc->data, data_len);
1191 silc_buffer_pull(enc, data_len);
1192 silc_hmac_final(sha1hmac, enc->data, NULL);
1193 silc_buffer_push(enc, data_len);
1196 memset(keymat, 0, sizeof(keymat));
1197 memset(tmp, 0, sizeof(tmp));
1198 silc_hmac_free(sha1hmac);
1199 silc_hash_free(md5);
1200 silc_cipher_free(aes);
1203 data_len = enc->len;
1206 case SILC_PKCS_FILE_BIN:
1208 case SILC_PKCS_FILE_PEM:
1209 data = silc_pem_encode_file(data, data_len);
1210 data_len = strlen(data);
1214 /* Encode the data and save to file */
1215 len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1216 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1217 buf = silc_buffer_alloc_size(len);
1218 silc_buffer_format(buf,
1219 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
1220 SILC_STR_UI_XNSTRING(data, data_len),
1221 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
1224 /* Save into a file */
1225 if (silc_file_writefile_mode(filename, buf->data, buf->len, 0600)) {
1226 silc_buffer_clear(buf);
1227 silc_buffer_free(buf);
1228 silc_buffer_clear(enc);
1229 silc_buffer_free(enc);
1233 silc_buffer_clear(buf);
1234 silc_buffer_free(buf);
1235 silc_buffer_clear(enc);
1236 silc_buffer_free(enc);
1240 /* Saves private key into file. */
1242 bool silc_pkcs_save_private_key(char *filename, SilcPrivateKey private_key,
1243 unsigned char *passphrase,
1244 SilcUInt32 passphrase_len,
1245 SilcUInt32 encoding)
1247 unsigned char *data;
1248 SilcUInt32 data_len;
1251 data = silc_pkcs_private_key_encode(private_key, &data_len);
1252 ret = silc_pkcs_save_private_key_internal(filename, data, data_len,
1253 passphrase, passphrase_len,
1255 memset(data, 0, data_len);
1260 /* Loads public key from file and allocates new public key. Returns TRUE
1261 if loading was successful. */
1263 bool silc_pkcs_load_public_key(char *filename, SilcPublicKey *public_key,
1264 SilcUInt32 encoding)
1266 unsigned char *cp, *old, *data, byte;
1267 SilcUInt32 i, data_len, len;
1269 old = data = silc_file_readfile(filename, &data_len);
1273 /* Check start of file and remove header from the data. */
1274 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
1276 for (i = 0; i < len; i++) {
1279 if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
1280 memset(old, 0, data_len);
1287 /* Decode public key */
1289 len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1290 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1293 case SILC_PKCS_FILE_BIN:
1295 case SILC_PKCS_FILE_PEM:
1296 data = silc_pem_decode(data, len, &len);
1297 memset(old, 0, data_len);
1304 if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
1305 memset(old, 0, data_len);
1311 memset(old, 0, data_len);
1316 /* Load private key from file and allocates new private key. Returns TRUE
1317 if loading was successful. */
1319 bool silc_pkcs_load_private_key(char *filename, SilcPrivateKey *private_key,
1320 unsigned char *passphrase,
1321 SilcUInt32 passphrase_len,
1322 SilcUInt32 encoding)
1327 SilcUInt32 blocklen;
1328 unsigned char tmp[32], keymat[32];
1329 unsigned char *cp, *old, *data, byte;
1330 SilcUInt32 i, data_len, len, magic, mac_len;
1332 old = data = silc_file_readfile(filename, &data_len);
1336 /* Check start of file and remove header from the data. */
1337 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
1339 for (i = 0; i < len; i++) {
1342 if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
1343 memset(old, 0, data_len);
1350 /* Decode private key */
1351 len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1352 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1355 case SILC_PKCS_FILE_BIN:
1357 case SILC_PKCS_FILE_PEM:
1358 data = silc_pem_decode(data, len, &len);
1360 memset(old, 0, data_len);
1367 memset(tmp, 0, sizeof(tmp));
1368 memset(keymat, 0, sizeof(keymat));
1370 /* Private key files without the specific magic number are assumed
1371 to be the old-style private keys that are not encrypted. */
1372 SILC_GET32_MSB(magic, data);
1373 if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
1374 SILC_LOG_DEBUG(("Private key does not have correct magic!"));
1376 /* Now decode the actual private key */
1377 if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1378 memset(old, 0, data_len);
1383 memset(old, 0, data_len);
1388 /* Allocate the AES cipher */
1389 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1390 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1391 memset(old, 0, data_len);
1395 blocklen = silc_cipher_get_block_len(aes);
1396 if (blocklen * 2 > sizeof(tmp)) {
1397 memset(old, 0, data_len);
1402 /* Allocate MD5 hash */
1403 if (!silc_hash_alloc("md5", &md5)) {
1404 SILC_LOG_ERROR(("Could not allocate MD5 hash, probably not registered"));
1405 silc_cipher_free(aes);
1406 memset(old, 0, data_len);
1412 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1413 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1414 silc_hash_free(md5);
1415 silc_cipher_free(aes);
1416 memset(old, 0, data_len);
1421 /* Derive the decryption key from the provided key material. The key
1422 is 256 bits length, and derived by taking hash of the data, then
1423 re-hashing the data and the previous digest, and using the first and
1424 second digest as the key. */
1425 silc_hash_init(md5);
1426 silc_hash_update(md5, passphrase, passphrase_len);
1427 silc_hash_final(md5, keymat);
1428 silc_hash_init(md5);
1429 silc_hash_update(md5, passphrase, passphrase_len);
1430 silc_hash_update(md5, keymat, 16);
1431 silc_hash_final(md5, keymat + 16);
1433 /* Set the key to the cipher */
1434 silc_cipher_set_key(aes, keymat, sizeof(keymat) * 8);
1436 /* First, verify the MAC of the private key data */
1437 mac_len = silc_hmac_len(sha1hmac);
1438 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1439 silc_hmac_update(sha1hmac, data, len - mac_len);
1440 silc_hmac_final(sha1hmac, tmp, NULL);
1441 if (memcmp(tmp, data + (len - mac_len), mac_len)) {
1442 SILC_LOG_DEBUG(("Integrity check for private key failed"));
1443 memset(keymat, 0, sizeof(keymat));
1444 memset(tmp, 0, sizeof(tmp));
1445 silc_hmac_free(sha1hmac);
1446 silc_hash_free(md5);
1447 silc_cipher_free(aes);
1448 memset(old, 0, data_len);
1455 /* Decrypt the private key buffer */
1456 silc_cipher_decrypt(aes, data, data, len - mac_len, silc_cipher_get_iv(aes));
1457 SILC_GET32_MSB(i, data);
1459 SILC_LOG_DEBUG(("Bad private key length in buffer!"));
1460 memset(keymat, 0, sizeof(keymat));
1461 memset(tmp, 0, sizeof(tmp));
1462 silc_hmac_free(sha1hmac);
1463 silc_hash_free(md5);
1464 silc_cipher_free(aes);
1465 memset(old, 0, data_len);
1473 memset(keymat, 0, sizeof(keymat));
1474 memset(tmp, 0, sizeof(tmp));
1475 silc_hmac_free(sha1hmac);
1476 silc_hash_free(md5);
1477 silc_cipher_free(aes);
1479 /* Now decode the actual private key */
1480 if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1481 memset(old, 0, data_len);
1486 memset(old, 0, data_len);