5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2003 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 bool ret = pkcs->pkcs->init(pkcs->context, bits_key_len, rng);
298 pkcs->key_len = bits_key_len;
302 /* Returns the length of the key */
304 SilcUInt32 silc_pkcs_get_key_len(SilcPKCS pkcs)
306 return pkcs->key_len;
309 const char *silc_pkcs_get_name(SilcPKCS pkcs)
311 return pkcs->pkcs->name;
314 /* Returns SILC style public key */
316 unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, SilcUInt32 *len)
318 return pkcs->pkcs->get_public_key(pkcs->context, len);
321 /* Returns SILC style private key */
323 unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, SilcUInt32 *len)
325 return pkcs->pkcs->get_private_key(pkcs->context, len);
328 /* Sets public key from SilcPublicKey. */
330 SilcUInt32 silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
332 pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
334 return pkcs->key_len;
337 /* Sets public key from data. */
339 SilcUInt32 silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
342 pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, pk, pk_len);
343 return pkcs->key_len;
346 /* Sets private key from SilcPrivateKey. */
348 SilcUInt32 silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
351 key_len = pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
352 private_key->prv_len);
354 pkcs->key_len = key_len;
355 return pkcs->key_len;
358 /* Sets private key from data. */
360 SilcUInt32 silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
364 key_len = pkcs->pkcs->set_private_key(pkcs->context, prv, prv_len);
366 pkcs->key_len = key_len;
367 return pkcs->key_len;
372 bool silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
373 unsigned char *dst, SilcUInt32 *dst_len)
375 return pkcs->pkcs->encrypt(pkcs->context, src, src_len, dst, dst_len);
380 bool silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
381 unsigned char *dst, SilcUInt32 *dst_len)
383 return pkcs->pkcs->decrypt(pkcs->context, src, src_len, dst, dst_len);
386 /* Generates signature */
388 bool silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
389 unsigned char *dst, SilcUInt32 *dst_len)
391 return pkcs->pkcs->sign(pkcs->context, src, src_len, dst, dst_len);
394 /* Verifies signature */
396 bool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
397 SilcUInt32 signature_len, unsigned char *data,
400 return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
404 /* Generates signature with hash. The hash is signed. */
406 bool silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
407 unsigned char *src, SilcUInt32 src_len,
408 unsigned char *dst, SilcUInt32 *dst_len)
410 unsigned char hashr[32];
414 silc_hash_make(hash, src, src_len, hashr);
415 hash_len = silc_hash_len(hash);
417 SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
419 ret = pkcs->pkcs->sign(pkcs->context, hashr, hash_len, dst, dst_len);
420 memset(hashr, 0, sizeof(hashr));
425 /* Verifies signature with hash. The `data' is hashed and verified against
428 bool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
429 unsigned char *signature,
430 SilcUInt32 signature_len,
434 unsigned char hashr[32];
438 silc_hash_make(hash, data, data_len, hashr);
439 hash_len = silc_hash_len(hash);
441 SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
443 ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
445 memset(hashr, 0, sizeof(hashr));
450 /* Encodes and returns SILC public key identifier. If some of the
451 arguments is NULL those are not encoded into the identifier string.
452 Protocol says that at least username and host must be provided. */
454 char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
455 char *email, char *org, char *country)
459 SilcUInt32 len, tlen = 0;
461 if (!username || !host)
464 len = (username ? strlen(username) : 0) +
465 (host ? strlen(host) : 0) +
466 (realname ? strlen(realname) : 0) +
467 (email ? strlen(email) : 0) +
468 (org ? strlen(org) : 0) +
469 (country ? strlen(country) : 0);
474 len += 3 + 5 + 5 + 4 + 4 + 4;
475 buf = silc_buffer_alloc(len);
476 silc_buffer_pull_tail(buf, len);
479 silc_buffer_format(buf,
480 SILC_STR_UI32_STRING("UN="),
481 SILC_STR_UI32_STRING(username),
483 silc_buffer_pull(buf, 3 + strlen(username));
484 tlen = 3 + strlen(username);
488 silc_buffer_format(buf,
489 SILC_STR_UI32_STRING(", "),
490 SILC_STR_UI32_STRING("HN="),
491 SILC_STR_UI32_STRING(host),
493 silc_buffer_pull(buf, 5 + strlen(host));
494 tlen += 5 + strlen(host);
498 silc_buffer_format(buf,
499 SILC_STR_UI32_STRING(", "),
500 SILC_STR_UI32_STRING("RN="),
501 SILC_STR_UI32_STRING(realname),
503 silc_buffer_pull(buf, 5 + strlen(realname));
504 tlen += 5 + strlen(realname);
508 silc_buffer_format(buf,
509 SILC_STR_UI32_STRING(", "),
510 SILC_STR_UI32_STRING("E="),
511 SILC_STR_UI32_STRING(email),
513 silc_buffer_pull(buf, 4 + strlen(email));
514 tlen += 4 + strlen(email);
518 silc_buffer_format(buf,
519 SILC_STR_UI32_STRING(", "),
520 SILC_STR_UI32_STRING("O="),
521 SILC_STR_UI32_STRING(org),
523 silc_buffer_pull(buf, 4 + strlen(org));
524 tlen += 4 + strlen(org);
528 silc_buffer_format(buf,
529 SILC_STR_UI32_STRING(", "),
530 SILC_STR_UI32_STRING("C="),
531 SILC_STR_UI32_STRING(country),
533 silc_buffer_pull(buf, 4 + strlen(country));
534 tlen += 4 + strlen(country);
537 silc_buffer_push(buf, buf->data - buf->head);
538 identifier = silc_calloc(tlen + 1, sizeof(*identifier));
539 memcpy(identifier, buf->data, tlen);
540 silc_buffer_free(buf);
545 /* Decodes the provided `identifier' and returns allocated context for
548 SilcPublicKeyIdentifier silc_pkcs_decode_identifier(char *identifier)
550 SilcPublicKeyIdentifier ident;
554 ident = silc_calloc(1, sizeof(*ident));
558 len = strcspn(cp, ",");
563 if (len - 1 >= 0 && cp[len - 1] == '\\') {
565 if (len + 1 > strlen(cp)) {
570 len = strcspn(cp, ",") + len;
575 if (len - 1 >= 0 && cp[len - 1] != '\\')
583 item = silc_calloc(len + 1, sizeof(char));
584 if (len > strlen(cp))
586 memcpy(item, cp, len);
588 if (strstr(item, "UN="))
589 ident->username = strdup(item + strcspn(cp, "=") + 1);
590 else if (strstr(item, "HN="))
591 ident->host = strdup(item + strcspn(cp, "=") + 1);
592 else if (strstr(item, "RN="))
593 ident->realname = strdup(item + strcspn(cp, "=") + 1);
594 else if (strstr(item, "E="))
595 ident->email = strdup(item + strcspn(cp, "=") + 1);
596 else if (strstr(item, "O="))
597 ident->org = strdup(item + strcspn(cp, "=") + 1);
598 else if (strstr(item, "C="))
599 ident->country = strdup(item + strcspn(cp, "=") + 1);
614 /* Free's decoded public key identifier context. Call this to free the
615 context returned by the silc_pkcs_decode_identifier. */
617 void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier)
619 silc_free(identifier->username);
620 silc_free(identifier->host);
621 silc_free(identifier->realname);
622 silc_free(identifier->email);
623 silc_free(identifier->org);
624 silc_free(identifier->country);
625 silc_free(identifier);
628 /* Allocates SILC style public key formed from sent arguments. All data
631 SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
632 const char *identifier,
633 const unsigned char *pk,
636 SilcPublicKey public_key;
639 public_key = silc_calloc(1, sizeof(*public_key));
640 public_key->name = strdup(name);
641 public_key->pk_len = pk_len;
642 public_key->pk = silc_memdup(pk, pk_len);
643 public_key->pk_type = SILC_SKE_PK_TYPE_SILC;
645 if (!silc_utf8_valid(identifier, strlen(identifier))) {
646 int len = silc_utf8_encoded_len(identifier, strlen(identifier), 0);
647 tmp = silc_calloc(len + 1, sizeof(*tmp));
648 silc_utf8_encode(identifier, strlen(identifier), 0, tmp, len);
652 public_key->identifier = strdup(identifier);
653 public_key->len = 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
659 /* Free's public key */
661 void silc_pkcs_public_key_free(SilcPublicKey public_key)
664 silc_free(public_key->name);
665 silc_free(public_key->identifier);
666 silc_free(public_key->pk);
667 silc_free(public_key);
671 /* Allocates SILC private key formed from sent arguments. All data is
674 SilcPrivateKey silc_pkcs_private_key_alloc(const char *name,
675 const unsigned char *prv,
678 SilcPrivateKey private_key;
680 private_key = silc_calloc(1, sizeof(*private_key));
681 private_key->name = strdup(name);
682 private_key->prv_len = prv_len;
683 private_key->prv = silc_memdup(prv, prv_len);
688 /* Free's private key */
690 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
693 silc_free(private_key->name);
694 if (private_key->prv) {
695 memset(private_key->prv, 0, private_key->prv_len);
696 silc_free(private_key->prv);
698 silc_free(private_key);
702 /* Encodes SILC style public key from SilcPublicKey. Returns the encoded
706 silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len)
708 return silc_pkcs_public_key_data_encode(public_key->pk,
711 public_key->identifier, len);
714 /* Encodes SILC style public key. Returns the encoded data. */
717 silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
718 char *pkcs, char *identifier,
725 totlen = 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
726 buf = silc_buffer_alloc_size(totlen + 4);
730 silc_buffer_format(buf,
731 SILC_STR_UI_INT(totlen),
732 SILC_STR_UI_SHORT(strlen(pkcs)),
733 SILC_STR_UI32_STRING(pkcs),
734 SILC_STR_UI_SHORT(strlen(identifier)),
735 SILC_STR_UI32_STRING(identifier),
736 SILC_STR_UI_XNSTRING(pk, pk_len),
739 ret = silc_buffer_steal(buf, len);
740 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)
750 SilcBufferStruct buf;
752 SilcUInt16 pkcs_len, identifier_len;
753 SilcUInt32 totlen, key_len;
754 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
757 silc_buffer_set(&buf, data, data_len);
760 ret = silc_buffer_unformat(&buf,
761 SILC_STR_UI_INT(&totlen),
766 #if 1 /* Backwards support, remove! */
767 if (totlen == data_len)
771 if (totlen + 4 != data_len)
774 /* Get algorithm name and identifier */
775 silc_buffer_pull(&buf, 4);
777 silc_buffer_unformat(&buf,
778 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
779 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
784 if (pkcs_len < 1 || identifier_len < 3 ||
785 pkcs_len + identifier_len > totlen)
788 /* See if we support this algorithm (check only if PKCS are registered) */
789 if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
790 SILC_LOG_DEBUG(("Unknown PKCS %s", pkcs_name));
794 /* Protocol says that at least UN and HN must be provided as identifier,
796 if (!strstr(ident, "UN=") && !strstr(ident, "HN=")) {
797 SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
802 /* Get key data. We assume that rest of the buffer is key data. */
803 silc_buffer_pull(&buf, 2 + pkcs_len + 2 + identifier_len);
805 ret = silc_buffer_unformat(&buf,
806 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
811 /* Try to set the key. If this fails the key must be malformed. This
812 code assumes that the PKCS routine checks the format of the key.
813 (check only if PKCS are registered) */
814 if (SILC_PKCS_LIST) {
815 silc_pkcs_alloc(pkcs_name, &alg);
816 if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
822 *public_key = silc_calloc(1, sizeof(**public_key));
823 (*public_key)->len = totlen;
824 (*public_key)->name = pkcs_name;
825 (*public_key)->identifier = ident;
826 (*public_key)->pk = key_data;
827 (*public_key)->pk_len = key_len;
828 (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
834 silc_free(pkcs_name);
840 /* Encodes Public Key Payload for transmitting public keys and certificates. */
842 SilcBuffer silc_pkcs_public_key_payload_encode(SilcPublicKey public_key)
851 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
855 buffer = silc_buffer_alloc_size(4 + pk_len);
861 silc_buffer_format(buffer,
862 SILC_STR_UI_SHORT(pk_len),
863 SILC_STR_UI_SHORT(public_key->pk_type),
864 SILC_STR_UI_XNSTRING(pk, pk_len),
871 /* Decode Public Key Payload and decodes the public key inside it to
874 bool silc_pkcs_public_key_payload_decode(unsigned char *data,
876 SilcPublicKey *public_key)
878 SilcBufferStruct buf;
879 SilcUInt16 pk_len, pk_type;
886 silc_buffer_set(&buf, data, data_len);
887 ret = silc_buffer_unformat(&buf,
888 SILC_STR_UI_SHORT(&pk_len),
889 SILC_STR_UI_SHORT(&pk_type),
891 if (ret < 0 || pk_len > data_len - 4)
894 /* For now we support only SILC public keys */
895 if (pk_type != SILC_SKE_PK_TYPE_SILC)
898 silc_buffer_pull(&buf, 4);
899 ret = silc_buffer_unformat(&buf,
900 SILC_STR_UI_XNSTRING(&pk, pk_len),
902 silc_buffer_push(&buf, 4);
906 if (!silc_pkcs_public_key_decode(pk, pk_len, public_key))
908 (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
913 /* Compares two public keys and returns TRUE if they are same key, and
914 FALSE if they are not same. */
916 bool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
921 if (key1->len == key2->len &&
922 key1->name && key2->name && key1->identifier && key2->identifier &&
923 !strcmp(key1->name, key2->name) &&
924 !strcmp(key1->identifier, key2->identifier) &&
925 !memcmp(key1->pk, key2->pk, key1->pk_len) &&
926 key1->pk_len == key2->pk_len)
932 /* Copies the public key indicated by `public_key' and returns new allocated
933 public key which is indentical to the `public_key'. */
935 SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
937 SilcPublicKey key = silc_calloc(1, sizeof(*key));
941 key->len = public_key->len;
942 key->name = silc_memdup(public_key->name, strlen(public_key->name));
943 key->identifier = silc_memdup(public_key->identifier,
944 strlen(public_key->identifier));
945 key->pk = silc_memdup(public_key->pk, public_key->pk_len);
946 key->pk_len = public_key->pk_len;
947 key->pk_type = public_key->pk_type;
952 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
955 silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
957 return silc_pkcs_private_key_data_encode(private_key->prv,
958 private_key->prv_len,
959 private_key->name, len);
962 /* Encodes SILC private key. Returns the encoded data. */
965 silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
966 char *pkcs, SilcUInt32 *len)
972 totlen = 2 + strlen(pkcs) + prv_len;
973 buf = silc_buffer_alloc_size(totlen);
977 silc_buffer_format(buf,
978 SILC_STR_UI_SHORT(strlen(pkcs)),
979 SILC_STR_UI32_STRING(pkcs),
980 SILC_STR_UI_XNSTRING(prv, prv_len),
983 ret = silc_buffer_steal(buf, len);
984 silc_buffer_free(buf);
988 /* Decodes SILC style private key. Returns TRUE if the decoding was
989 successful. Allocates new private key as well. */
991 bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
992 SilcPrivateKey *private_key)
994 SilcBufferStruct buf;
998 unsigned char *pkcs_name = NULL, *key_data = NULL;
1001 silc_buffer_set(&buf, data, data_len);
1003 /* Get algorithm name and identifier */
1005 silc_buffer_unformat(&buf,
1006 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
1009 SILC_LOG_DEBUG(("Cannot decode private key buffer"));
1013 if (pkcs_len < 1 || pkcs_len > buf.truelen) {
1014 SILC_LOG_DEBUG(("Malformed private key buffer"));
1018 /* See if we support this algorithm (check only if PKCS are registered). */
1019 if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
1020 SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
1024 /* Get key data. We assume that rest of the buffer is key data. */
1025 silc_buffer_pull(&buf, 2 + pkcs_len);
1027 ret = silc_buffer_unformat(&buf,
1028 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
1033 /* Try to set the key. If this fails the key must be malformed. This
1034 code assumes that the PKCS routine checks the format of the key.
1035 (check only if PKCS are registered) */
1036 if (SILC_PKCS_LIST) {
1037 silc_pkcs_alloc(pkcs_name, &alg);
1038 if (!alg->pkcs->set_private_key(alg->context, key_data, key_len)) {
1039 SILC_LOG_DEBUG(("Could not set private key data"));
1042 silc_pkcs_free(alg);
1046 *private_key = silc_calloc(1, sizeof(**private_key));
1047 (*private_key)->name = pkcs_name;
1048 (*private_key)->prv = key_data;
1049 (*private_key)->prv_len = key_len;
1055 silc_free(pkcs_name);
1056 silc_free(key_data);
1060 /* Internal routine to save public key */
1062 static bool silc_pkcs_save_public_key_internal(const char *filename,
1063 unsigned char *data,
1064 SilcUInt32 data_len,
1065 SilcUInt32 encoding)
1069 unsigned char *tmp = NULL;
1072 case SILC_PKCS_FILE_BIN:
1074 case SILC_PKCS_FILE_PEM:
1075 tmp = data = silc_pem_encode_file(data, data_len);
1076 data_len = strlen(data);
1080 len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1081 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1082 buf = silc_buffer_alloc_size(len);
1088 silc_buffer_format(buf,
1089 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
1090 SILC_STR_UI_XNSTRING(data, data_len),
1091 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
1094 /* Save into file */
1095 if (silc_file_writefile(filename, buf->data, buf->len)) {
1097 silc_buffer_free(buf);
1102 silc_buffer_free(buf);
1106 /* Saves public key into file */
1108 bool silc_pkcs_save_public_key(const char *filename, SilcPublicKey public_key,
1109 SilcUInt32 encoding)
1111 unsigned char *data;
1112 SilcUInt32 data_len;
1115 data = silc_pkcs_public_key_encode(public_key, &data_len);
1116 ret = silc_pkcs_save_public_key_internal(filename, data, data_len,
1122 /* Saves public key into file */
1124 bool silc_pkcs_save_public_key_data(const char *filename, unsigned char *data,
1125 SilcUInt32 data_len, SilcUInt32 encoding)
1127 return silc_pkcs_save_public_key_internal(filename, data, data_len,
1131 #define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
1133 /* Internal routine to save private key. */
1135 static bool silc_pkcs_save_private_key_internal(const char *filename,
1136 unsigned char *data,
1137 SilcUInt32 data_len,
1140 SilcUInt32 encoding)
1145 SilcBuffer buf, enc;
1146 SilcUInt32 len, blocklen, padlen;
1147 unsigned char tmp[32], keymat[64];
1150 memset(tmp, 0, sizeof(tmp));
1151 memset(keymat, 0, sizeof(keymat));
1153 /* Allocate the AES cipher */
1154 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1155 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1158 blocklen = silc_cipher_get_block_len(aes);
1159 if (blocklen * 2 > sizeof(tmp))
1162 /* Allocate SHA1 hash */
1163 if (!silc_hash_alloc("sha1", &sha1)) {
1164 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1165 silc_cipher_free(aes);
1170 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1171 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1172 silc_hash_free(sha1);
1173 silc_cipher_free(aes);
1177 /* Derive the encryption key from the provided key material. The key
1178 is 256 bits length, and derived by taking hash of the data, then
1179 re-hashing the data and the previous digest, and using the first and
1180 second digest as the key. */
1181 silc_hash_init(sha1);
1182 silc_hash_update(sha1, key, key_len);
1183 silc_hash_final(sha1, keymat);
1184 silc_hash_init(sha1);
1185 silc_hash_update(sha1, key, key_len);
1186 silc_hash_update(sha1, keymat, 16);
1187 silc_hash_final(sha1, keymat + 16);
1189 /* Set the key to the cipher */
1190 silc_cipher_set_key(aes, keymat, 256);
1192 /* Encode the buffer to be encrypted. Add padding to it too, at least
1193 block size of the cipher. */
1195 /* Allocate buffer for encryption */
1196 len = silc_hmac_len(sha1hmac);
1197 padlen = 16 + (16 - ((data_len + 4) % blocklen));
1198 enc = silc_buffer_alloc_size(4 + 4 + data_len + padlen + len);
1200 silc_hmac_free(sha1hmac);
1201 silc_hash_free(sha1);
1202 silc_cipher_free(aes);
1206 /* Generate padding */
1207 for (i = 0; i < padlen; i++)
1208 tmp[i] = silc_rng_global_get_byte_fast();
1210 /* Put magic number */
1211 SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
1212 silc_buffer_pull(enc, 4);
1214 /* Encode the buffer */
1215 silc_buffer_format(enc,
1216 SILC_STR_UI_INT(data_len),
1217 SILC_STR_UI_XNSTRING(data, data_len),
1218 SILC_STR_UI_XNSTRING(tmp, padlen),
1222 silc_cipher_encrypt(aes, enc->data, enc->data, enc->len - len,
1223 silc_cipher_get_iv(aes));
1225 silc_buffer_push(enc, 4);
1227 /* Compute HMAC over the encrypted data and append the MAC to data.
1228 The key is the first digest of the original key material. */
1229 data_len = enc->len - len;
1230 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1231 silc_hmac_update(sha1hmac, enc->data, data_len);
1232 silc_buffer_pull(enc, data_len);
1233 silc_hmac_final(sha1hmac, enc->data, NULL);
1234 silc_buffer_push(enc, data_len);
1237 memset(keymat, 0, sizeof(keymat));
1238 memset(tmp, 0, sizeof(tmp));
1239 silc_hmac_free(sha1hmac);
1240 silc_hash_free(sha1);
1241 silc_cipher_free(aes);
1244 data_len = enc->len;
1247 case SILC_PKCS_FILE_BIN:
1249 case SILC_PKCS_FILE_PEM:
1250 data = silc_pem_encode_file(data, data_len);
1251 data_len = strlen(data);
1255 /* Encode the data and save to file */
1256 len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1257 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1258 buf = silc_buffer_alloc_size(len);
1259 silc_buffer_format(buf,
1260 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
1261 SILC_STR_UI_XNSTRING(data, data_len),
1262 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
1265 /* Save into a file */
1266 if (silc_file_writefile_mode(filename, buf->data, buf->len, 0600)) {
1267 silc_buffer_clear(buf);
1268 silc_buffer_free(buf);
1269 silc_buffer_clear(enc);
1270 silc_buffer_free(enc);
1274 silc_buffer_clear(buf);
1275 silc_buffer_free(buf);
1276 silc_buffer_clear(enc);
1277 silc_buffer_free(enc);
1281 /* Saves private key into file. */
1283 bool silc_pkcs_save_private_key(const char *filename,
1284 SilcPrivateKey private_key,
1285 unsigned char *passphrase,
1286 SilcUInt32 passphrase_len,
1287 SilcUInt32 encoding)
1289 unsigned char *data;
1290 SilcUInt32 data_len;
1293 data = silc_pkcs_private_key_encode(private_key, &data_len);
1294 ret = silc_pkcs_save_private_key_internal(filename, data, data_len,
1295 passphrase, passphrase_len,
1297 memset(data, 0, data_len);
1302 /* Loads public key from file and allocates new public key. Returns TRUE
1303 if loading was successful. */
1305 bool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key,
1306 SilcUInt32 encoding)
1308 unsigned char *cp, *old, *data, byte;
1309 SilcUInt32 i, data_len, len;
1311 SILC_LOG_DEBUG(("Loading public key `%s' with %s encoding", filename,
1312 encoding == SILC_PKCS_FILE_PEM ? "Base64" :
1313 encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
1315 old = data = silc_file_readfile(filename, &data_len);
1319 /* Check start of file and remove header from the data. */
1320 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
1322 for (i = 0; i < len; i++) {
1325 if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
1326 memset(old, 0, data_len);
1333 /* Decode public key */
1335 len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1336 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1339 case SILC_PKCS_FILE_BIN:
1341 case SILC_PKCS_FILE_PEM:
1342 data = silc_pem_decode(data, len, &len);
1343 memset(old, 0, data_len);
1350 if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
1351 memset(old, 0, data_len);
1357 memset(old, 0, data_len);
1362 /* Load private key from file and allocates new private key. Returns TRUE
1363 if loading was successful. */
1365 bool silc_pkcs_load_private_key(const char *filename,
1366 SilcPrivateKey *private_key,
1367 unsigned char *passphrase,
1368 SilcUInt32 passphrase_len,
1369 SilcUInt32 encoding)
1374 SilcUInt32 blocklen;
1375 unsigned char tmp[32], keymat[64];
1376 unsigned char *cp, *old, *data, byte;
1377 SilcUInt32 i, data_len, len, magic, mac_len;
1379 SILC_LOG_DEBUG(("Loading private key `%s' with %s encoding", filename,
1380 encoding == SILC_PKCS_FILE_PEM ? "Base64" :
1381 encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
1383 old = data = silc_file_readfile(filename, &data_len);
1387 /* Check start of file and remove header from the data. */
1388 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
1390 for (i = 0; i < len; i++) {
1393 if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
1394 memset(old, 0, data_len);
1401 /* Decode private key */
1402 len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1403 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1406 case SILC_PKCS_FILE_BIN:
1408 case SILC_PKCS_FILE_PEM:
1409 data = silc_pem_decode(data, len, &len);
1411 memset(old, 0, data_len);
1418 memset(tmp, 0, sizeof(tmp));
1419 memset(keymat, 0, sizeof(keymat));
1421 /* Private key files without the specific magic number are assumed
1422 to be the old-style private keys that are not encrypted. */
1423 SILC_GET32_MSB(magic, data);
1424 if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
1425 SILC_LOG_DEBUG(("Private key does not have correct magic!"));
1427 /* Now decode the actual private key */
1428 if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1429 memset(old, 0, data_len);
1434 memset(old, 0, data_len);
1439 /* Allocate the AES cipher */
1440 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1441 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1442 memset(old, 0, data_len);
1446 blocklen = silc_cipher_get_block_len(aes);
1447 if (blocklen * 2 > sizeof(tmp)) {
1448 memset(old, 0, data_len);
1453 /* Allocate SHA1 hash */
1454 if (!silc_hash_alloc("sha1", &sha1)) {
1455 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1456 silc_cipher_free(aes);
1457 memset(old, 0, data_len);
1463 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1464 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1465 silc_hash_free(sha1);
1466 silc_cipher_free(aes);
1467 memset(old, 0, data_len);
1472 /* Derive the decryption key from the provided key material. The key
1473 is 256 bits length, and derived by taking hash of the data, then
1474 re-hashing the data and the previous digest, and using the first and
1475 second digest as the key. */
1476 silc_hash_init(sha1);
1477 silc_hash_update(sha1, passphrase, passphrase_len);
1478 silc_hash_final(sha1, keymat);
1479 silc_hash_init(sha1);
1480 silc_hash_update(sha1, passphrase, passphrase_len);
1481 silc_hash_update(sha1, keymat, 16);
1482 silc_hash_final(sha1, keymat + 16);
1484 /* Set the key to the cipher */
1485 silc_cipher_set_key(aes, keymat, 256);
1487 /* First, verify the MAC of the private key data */
1488 mac_len = silc_hmac_len(sha1hmac);
1489 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1490 silc_hmac_update(sha1hmac, data, len - mac_len);
1491 silc_hmac_final(sha1hmac, tmp, NULL);
1492 if (memcmp(tmp, data + (len - mac_len), mac_len)) {
1493 SILC_LOG_DEBUG(("Integrity check for private key failed"));
1494 memset(keymat, 0, sizeof(keymat));
1495 memset(tmp, 0, sizeof(tmp));
1496 silc_hmac_free(sha1hmac);
1497 silc_hash_free(sha1);
1498 silc_cipher_free(aes);
1499 memset(old, 0, data_len);
1506 /* Decrypt the private key buffer */
1507 silc_cipher_decrypt(aes, data, data, len - mac_len, NULL);
1508 SILC_GET32_MSB(i, data);
1510 SILC_LOG_DEBUG(("Bad private key length in buffer!"));
1511 memset(keymat, 0, sizeof(keymat));
1512 memset(tmp, 0, sizeof(tmp));
1513 silc_hmac_free(sha1hmac);
1514 silc_hash_free(sha1);
1515 silc_cipher_free(aes);
1516 memset(old, 0, data_len);
1524 memset(keymat, 0, sizeof(keymat));
1525 memset(tmp, 0, sizeof(tmp));
1526 silc_hmac_free(sha1hmac);
1527 silc_hash_free(sha1);
1528 silc_cipher_free(aes);
1530 /* Now decode the actual private key */
1531 if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1532 memset(old, 0, data_len);
1537 memset(old, 0, data_len);