5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
25 /* The main SILC PKCS structure. */
26 struct SilcPKCSStruct {
27 void *context; /* Algorithm internal context */
28 SilcPKCSObject *pkcs; /* Algorithm implementation */
29 SilcUInt32 key_len; /* Key length in bits */
33 /* Dynamically registered list of PKCS. */
34 SilcDList silc_pkcs_list = NULL;
35 #define SILC_PKCS_LIST silc_pkcs_list
37 #define SILC_PKCS_LIST TRUE
38 #endif /* SILC_EPOC */
40 /* Static list of PKCS for silc_pkcs_register_default(). */
41 const SilcPKCSObject silc_default_pkcs[] =
43 /* RSA with PKCS #1 for SILC PKCS */
44 { "rsa", SILC_PKCS_SILC,
45 silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
46 silc_rsa_get_private_key, silc_rsa_set_public_key,
47 silc_rsa_set_private_key, silc_rsa_context_len,
48 silc_pkcs1_encrypt, silc_pkcs1_decrypt,
49 silc_pkcs1_sign, silc_pkcs1_verify },
51 /* RSASSA-PKCS1-V1_5 for SSH2 PKCS */
53 { "rsa", SILC_PKCS_SSH2,
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_pkcs1_encrypt, silc_pkcs1_decrypt,
58 silc_pkcs1_sign, silc_pkcs1_verify },
61 { NULL, 0, NULL, NULL, NULL, NULL,
62 NULL, NULL, NULL, NULL, NULL, NULL }
65 /* Register a new PKCS into SILC. This is used at the initialization of
68 SilcBool silc_pkcs_register(const SilcPKCSObject *pkcs)
73 SILC_LOG_DEBUG(("Registering new PKCS `%s'", pkcs->name));
75 /* Check if exists already */
77 SilcPKCSObject *entry;
78 silc_dlist_start(silc_pkcs_list);
79 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
80 if (!strcmp(entry->name, pkcs->name) &&
81 entry->type == pkcs->type)
86 new = silc_calloc(1, sizeof(*new));
87 new->name = strdup(pkcs->name);
88 new->type = pkcs->type;
89 new->init = pkcs->init;
90 new->clear_keys = pkcs->clear_keys;
91 new->get_public_key = pkcs->get_public_key;
92 new->get_private_key = pkcs->get_private_key;
93 new->set_public_key = pkcs->set_public_key;
94 new->set_private_key = pkcs->set_private_key;
95 new->context_len = pkcs->context_len;
96 new->encrypt = pkcs->encrypt;
97 new->decrypt = pkcs->decrypt;
98 new->sign = pkcs->sign;
99 new->verify = pkcs->verify;
102 if (silc_pkcs_list == NULL)
103 silc_pkcs_list = silc_dlist_init();
104 silc_dlist_add(silc_pkcs_list, new);
106 #endif /* SILC_EPOC */
110 /* Unregister a PKCS from the SILC. */
112 SilcBool silc_pkcs_unregister(SilcPKCSObject *pkcs)
115 SilcPKCSObject *entry;
117 SILC_LOG_DEBUG(("Unregistering PKCS"));
122 silc_dlist_start(silc_pkcs_list);
123 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
124 if (pkcs == SILC_ALL_PKCS || entry == pkcs) {
125 silc_dlist_del(silc_pkcs_list, entry);
126 silc_free(entry->name);
129 if (silc_dlist_count(silc_pkcs_list) == 0) {
130 silc_dlist_uninit(silc_pkcs_list);
131 silc_pkcs_list = NULL;
138 #endif /* SILC_EPOC */
142 /* Function that registers all the default PKCS (all builtin PKCS).
143 The application may use this to register the default PKCS if specific
144 PKCS in any specific order is not wanted. */
146 SilcBool silc_pkcs_register_default(void)
151 for (i = 0; silc_default_pkcs[i].name; i++)
152 silc_pkcs_register(&(silc_default_pkcs[i]));
154 #endif /* SILC_EPOC */
158 SilcBool silc_pkcs_unregister_all(void)
161 SilcPKCSObject *entry;
166 silc_dlist_start(silc_pkcs_list);
167 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
168 silc_pkcs_unregister(entry);
172 #endif /* SILC_EPOC */
176 /* Allocates a new SilcPKCS object. The new allocated object is returned
177 to the 'new_pkcs' argument. */
179 SilcBool silc_pkcs_alloc(const unsigned char *name, SilcPKCSType type,
182 SilcPKCSObject *entry = NULL;
184 SILC_LOG_DEBUG(("Allocating new PKCS object"));
187 if (silc_pkcs_list) {
188 silc_dlist_start(silc_pkcs_list);
189 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
190 if (!strcmp(entry->name, name) && entry->type == type)
196 /* On EPOC which don't have globals we check our constant hash list. */
198 for (i = 0; silc_default_pkcs[i].name; i++) {
199 if (!strcmp(silc_default_pkcs[i].name, name) &&
200 silc_default_pkcs[i].type == type) {
201 entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
206 #endif /* SILC_EPOC */
209 *new_pkcs = silc_calloc(1, sizeof(**new_pkcs));
210 (*new_pkcs)->pkcs = entry;
211 (*new_pkcs)->context = silc_calloc(1, entry->context_len());
218 /* Free's the PKCS object */
220 void silc_pkcs_free(SilcPKCS pkcs)
223 pkcs->pkcs->clear_keys(pkcs->context);
224 silc_free(pkcs->context);
229 /* Return TRUE if PKCS algorithm `name' is supported. */
231 SilcBool silc_pkcs_is_supported(const unsigned char *name)
234 SilcPKCSObject *entry;
236 if (silc_pkcs_list) {
237 silc_dlist_start(silc_pkcs_list);
238 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
239 if (!strcmp(entry->name, name))
246 for (i = 0; silc_default_pkcs[i].name; i++)
247 if (!strcmp(silc_default_pkcs[i].name, name))
250 #endif /* SILC_EPOC */
254 /* Returns comma separated list of supported PKCS algorithms */
256 char *silc_pkcs_get_supported(void)
258 SilcPKCSObject *entry;
263 if (silc_pkcs_list) {
264 silc_dlist_start(silc_pkcs_list);
265 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
266 len += strlen(entry->name);
267 list = silc_realloc(list, len + 1);
269 memcpy(list + (len - strlen(entry->name)),
270 entry->name, strlen(entry->name));
271 memcpy(list + len, ",", 1);
278 for (i = 0; silc_default_pkcs[i].name; i++) {
279 entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
280 len += strlen(entry->name);
281 list = silc_realloc(list, len + 1);
283 memcpy(list + (len - strlen(entry->name)),
284 entry->name, strlen(entry->name));
285 memcpy(list + len, ",", 1);
289 #endif /* SILC_EPOC */
296 /* Generate new key pair into the `pkcs' context. */
298 SilcBool silc_pkcs_generate_key(SilcPKCS pkcs, SilcUInt32 bits_key_len,
301 SilcBool ret = pkcs->pkcs->init(pkcs->context, bits_key_len, rng);
303 pkcs->key_len = bits_key_len;
307 /* Returns the length of the key */
309 SilcUInt32 silc_pkcs_get_key_len(SilcPKCS pkcs)
311 return pkcs->key_len;
314 const char *silc_pkcs_get_name(SilcPKCS pkcs)
316 return pkcs->pkcs->name;
319 /* Returns SILC style public key */
321 unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, SilcUInt32 *len)
323 return pkcs->pkcs->get_public_key(pkcs->context, len);
326 /* Returns SILC style private key */
328 unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, SilcUInt32 *len)
330 return pkcs->pkcs->get_private_key(pkcs->context, len);
333 /* Sets public key from SilcPublicKey. */
335 SilcUInt32 silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
337 pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
339 return pkcs->key_len;
342 /* Sets public key from data. */
344 SilcUInt32 silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
347 pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, pk, pk_len);
348 return pkcs->key_len;
351 /* Sets private key from SilcPrivateKey. */
353 SilcUInt32 silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
356 key_len = pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
357 private_key->prv_len);
359 pkcs->key_len = key_len;
360 return pkcs->key_len;
363 /* Sets private key from data. */
365 SilcUInt32 silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
369 key_len = pkcs->pkcs->set_private_key(pkcs->context, prv, prv_len);
371 pkcs->key_len = key_len;
372 return pkcs->key_len;
377 SilcBool silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
378 unsigned char *dst, SilcUInt32 *dst_len)
380 return pkcs->pkcs->encrypt(pkcs->context, src, src_len, dst, dst_len);
385 SilcBool silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
386 unsigned char *dst, SilcUInt32 *dst_len)
388 return pkcs->pkcs->decrypt(pkcs->context, src, src_len, dst, dst_len);
391 /* Generates signature */
393 SilcBool silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
394 unsigned char *dst, SilcUInt32 *dst_len)
396 return pkcs->pkcs->sign(pkcs->context, src, src_len, dst, dst_len);
399 /* Verifies signature */
401 SilcBool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
402 SilcUInt32 signature_len, unsigned char *data,
405 return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
409 /* Generates signature with hash. The hash is signed. */
411 SilcBool silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
412 unsigned char *src, SilcUInt32 src_len,
413 unsigned char *dst, SilcUInt32 *dst_len)
415 unsigned char hashr[SILC_HASH_MAXLEN];
419 silc_hash_make(hash, src, src_len, hashr);
420 hash_len = silc_hash_len(hash);
422 SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
424 ret = pkcs->pkcs->sign(pkcs->context, hashr, hash_len, dst, dst_len);
425 memset(hashr, 0, sizeof(hashr));
430 /* Verifies signature with hash. The `data' is hashed and verified against
433 SilcBool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
434 unsigned char *signature,
435 SilcUInt32 signature_len,
439 unsigned char hashr[SILC_HASH_MAXLEN];
443 silc_hash_make(hash, data, data_len, hashr);
444 hash_len = silc_hash_len(hash);
446 SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
448 ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
450 memset(hashr, 0, sizeof(hashr));
455 /* Encodes and returns SILC public key identifier. If some of the
456 arguments is NULL those are not encoded into the identifier string.
457 Protocol says that at least username and host must be provided. */
459 char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
460 char *email, char *org, char *country)
464 SilcUInt32 len, tlen = 0;
466 if (!username || !host)
469 len = (username ? strlen(username) : 0) +
470 (host ? strlen(host) : 0) +
471 (realname ? strlen(realname) : 0) +
472 (email ? strlen(email) : 0) +
473 (org ? strlen(org) : 0) +
474 (country ? strlen(country) : 0);
479 len += 3 + 5 + 5 + 4 + 4 + 4;
480 buf = silc_buffer_alloc(len);
481 silc_buffer_pull_tail(buf, len);
484 silc_buffer_format(buf,
485 SILC_STR_UI32_STRING("UN="),
486 SILC_STR_UI32_STRING(username),
488 silc_buffer_pull(buf, 3 + strlen(username));
489 tlen = 3 + strlen(username);
493 silc_buffer_format(buf,
494 SILC_STR_UI32_STRING(", "),
495 SILC_STR_UI32_STRING("HN="),
496 SILC_STR_UI32_STRING(host),
498 silc_buffer_pull(buf, 5 + strlen(host));
499 tlen += 5 + strlen(host);
503 silc_buffer_format(buf,
504 SILC_STR_UI32_STRING(", "),
505 SILC_STR_UI32_STRING("RN="),
506 SILC_STR_UI32_STRING(realname),
508 silc_buffer_pull(buf, 5 + strlen(realname));
509 tlen += 5 + strlen(realname);
513 silc_buffer_format(buf,
514 SILC_STR_UI32_STRING(", "),
515 SILC_STR_UI32_STRING("E="),
516 SILC_STR_UI32_STRING(email),
518 silc_buffer_pull(buf, 4 + strlen(email));
519 tlen += 4 + strlen(email);
523 silc_buffer_format(buf,
524 SILC_STR_UI32_STRING(", "),
525 SILC_STR_UI32_STRING("O="),
526 SILC_STR_UI32_STRING(org),
528 silc_buffer_pull(buf, 4 + strlen(org));
529 tlen += 4 + strlen(org);
533 silc_buffer_format(buf,
534 SILC_STR_UI32_STRING(", "),
535 SILC_STR_UI32_STRING("C="),
536 SILC_STR_UI32_STRING(country),
538 silc_buffer_pull(buf, 4 + strlen(country));
539 tlen += 4 + strlen(country);
542 silc_buffer_push(buf, buf->data - buf->head);
543 identifier = silc_calloc(tlen + 1, sizeof(*identifier));
544 memcpy(identifier, buf->data, tlen);
545 silc_buffer_free(buf);
550 /* Decodes the provided `identifier' and returns allocated context for
553 SilcPublicKeyIdentifier silc_pkcs_decode_identifier(char *identifier)
555 SilcPublicKeyIdentifier ident;
559 ident = silc_calloc(1, sizeof(*ident));
563 len = strcspn(cp, ",");
568 if (len - 1 >= 0 && cp[len - 1] == '\\') {
570 if (len + 1 > strlen(cp)) {
575 len = strcspn(cp, ",") + len;
580 if (len - 1 >= 0 && cp[len - 1] != '\\')
588 item = silc_calloc(len + 1, sizeof(char));
589 if (len > strlen(cp))
591 memcpy(item, cp, len);
593 if (strstr(item, "UN="))
594 ident->username = strdup(item + strcspn(cp, "=") + 1);
595 else if (strstr(item, "HN="))
596 ident->host = strdup(item + strcspn(cp, "=") + 1);
597 else if (strstr(item, "RN="))
598 ident->realname = strdup(item + strcspn(cp, "=") + 1);
599 else if (strstr(item, "E="))
600 ident->email = strdup(item + strcspn(cp, "=") + 1);
601 else if (strstr(item, "O="))
602 ident->org = strdup(item + strcspn(cp, "=") + 1);
603 else if (strstr(item, "C="))
604 ident->country = strdup(item + strcspn(cp, "=") + 1);
619 /* Free's decoded public key identifier context. Call this to free the
620 context returned by the silc_pkcs_decode_identifier. */
622 void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier)
624 silc_free(identifier->username);
625 silc_free(identifier->host);
626 silc_free(identifier->realname);
627 silc_free(identifier->email);
628 silc_free(identifier->org);
629 silc_free(identifier->country);
630 silc_free(identifier);
633 /* Allocates SILC style public key formed from sent arguments. All data
636 SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
637 const char *identifier,
638 const unsigned char *pk,
641 SilcPublicKey public_key;
644 public_key = silc_calloc(1, sizeof(*public_key));
645 public_key->name = strdup(name);
646 public_key->pk_len = pk_len;
647 public_key->pk = silc_memdup(pk, pk_len);
648 public_key->pk_type = SILC_SKE_PK_TYPE_SILC;
650 if (!silc_utf8_valid(identifier, strlen(identifier))) {
651 int len = silc_utf8_encoded_len(identifier, strlen(identifier), 0);
652 tmp = silc_calloc(len + 1, sizeof(*tmp));
653 silc_utf8_encode(identifier, strlen(identifier), 0, tmp, len);
657 public_key->identifier = strdup(identifier);
658 public_key->len = 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
664 /* Free's public key */
666 void silc_pkcs_public_key_free(SilcPublicKey public_key)
669 silc_free(public_key->name);
670 silc_free(public_key->identifier);
671 silc_free(public_key->pk);
672 silc_free(public_key);
676 /* Allocates SILC private key formed from sent arguments. All data is
679 SilcPrivateKey silc_pkcs_private_key_alloc(const char *name,
680 const unsigned char *prv,
683 SilcPrivateKey private_key;
685 private_key = silc_calloc(1, sizeof(*private_key));
686 private_key->name = strdup(name);
687 private_key->prv_len = prv_len;
688 private_key->prv = silc_memdup(prv, prv_len);
693 /* Free's private key */
695 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
698 silc_free(private_key->name);
699 if (private_key->prv) {
700 memset(private_key->prv, 0, private_key->prv_len);
701 silc_free(private_key->prv);
703 silc_free(private_key);
707 /* Encodes SILC style public key from SilcPublicKey. Returns the encoded
711 silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len)
713 return silc_pkcs_public_key_data_encode(public_key->pk,
716 public_key->identifier, len);
719 /* Encodes SILC style public key. Returns the encoded data. */
722 silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
723 char *pkcs, char *identifier,
730 totlen = 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
731 buf = silc_buffer_alloc_size(totlen + 4);
735 silc_buffer_format(buf,
736 SILC_STR_UI_INT(totlen),
737 SILC_STR_UI_SHORT(strlen(pkcs)),
738 SILC_STR_UI32_STRING(pkcs),
739 SILC_STR_UI_SHORT(strlen(identifier)),
740 SILC_STR_UI32_STRING(identifier),
741 SILC_STR_UI_XNSTRING(pk, pk_len),
744 ret = silc_buffer_steal(buf, len);
745 silc_buffer_free(buf);
749 /* Decodes SILC style public key. Returns TRUE if the decoding was
750 successful. Allocates new public key as well. */
752 SilcBool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
753 SilcPublicKey *public_key)
755 SilcBufferStruct buf;
757 SilcUInt16 pkcs_len, identifier_len;
758 SilcUInt32 totlen, key_len;
759 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
762 silc_buffer_set(&buf, data, data_len);
765 ret = silc_buffer_unformat(&buf,
766 SILC_STR_UI_INT(&totlen),
771 #if 1 /* Backwards support, remove! */
772 if (totlen == data_len)
776 if (totlen + 4 != data_len)
779 /* Get algorithm name and identifier */
780 silc_buffer_pull(&buf, 4);
782 silc_buffer_unformat(&buf,
783 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
784 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
789 if (pkcs_len < 1 || identifier_len < 3 ||
790 pkcs_len + identifier_len > totlen)
793 /* See if we support this algorithm (check only if PKCS are registered) */
794 if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
795 SILC_LOG_DEBUG(("Unknown PKCS %s", pkcs_name));
799 /* Protocol says that at least UN and HN must be provided as identifier,
801 if (!strstr(ident, "UN=") && !strstr(ident, "HN=")) {
802 SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
807 /* Get key data. We assume that rest of the buffer is key data. */
808 silc_buffer_pull(&buf, 2 + pkcs_len + 2 + identifier_len);
809 key_len = silc_buffer_len(&buf);
810 ret = silc_buffer_unformat(&buf,
811 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
816 /* Try to set the key. If this fails the key must be malformed. This
817 code assumes that the PKCS routine checks the format of the key.
818 (check only if PKCS are registered) */
819 if (SILC_PKCS_LIST) {
820 silc_pkcs_alloc(pkcs_name, SILC_PKCS_SILC, &alg);
821 if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
827 *public_key = silc_calloc(1, sizeof(**public_key));
828 (*public_key)->len = totlen;
829 (*public_key)->name = pkcs_name;
830 (*public_key)->identifier = ident;
831 (*public_key)->pk = key_data;
832 (*public_key)->pk_len = key_len;
833 (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
839 silc_free(pkcs_name);
845 /* Encodes Public Key Payload for transmitting public keys and certificates. */
847 SilcBuffer silc_pkcs_public_key_payload_encode(SilcPublicKey public_key)
856 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
860 buffer = silc_buffer_alloc_size(4 + pk_len);
866 silc_buffer_format(buffer,
867 SILC_STR_UI_SHORT(pk_len),
868 SILC_STR_UI_SHORT(public_key->pk_type),
869 SILC_STR_UI_XNSTRING(pk, pk_len),
876 /* Decode Public Key Payload and decodes the public key inside it to
879 SilcBool silc_pkcs_public_key_payload_decode(unsigned char *data,
881 SilcPublicKey *public_key)
883 SilcBufferStruct buf;
884 SilcUInt16 pk_len, pk_type;
891 silc_buffer_set(&buf, data, data_len);
892 ret = silc_buffer_unformat(&buf,
893 SILC_STR_UI_SHORT(&pk_len),
894 SILC_STR_UI_SHORT(&pk_type),
896 if (ret < 0 || pk_len > data_len - 4)
899 /* For now we support only SILC public keys */
900 if (pk_type != SILC_SKE_PK_TYPE_SILC)
903 silc_buffer_pull(&buf, 4);
904 ret = silc_buffer_unformat(&buf,
905 SILC_STR_UI_XNSTRING(&pk, pk_len),
907 silc_buffer_push(&buf, 4);
911 if (!silc_pkcs_public_key_decode(pk, pk_len, public_key))
913 (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
918 /* Compares two public keys and returns TRUE if they are same key, and
919 FALSE if they are not same. */
921 SilcBool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
926 if (key1->len == key2->len &&
927 key1->name && key2->name && key1->identifier && key2->identifier &&
928 !strcmp(key1->name, key2->name) &&
929 !strcmp(key1->identifier, key2->identifier) &&
930 !memcmp(key1->pk, key2->pk, key1->pk_len) &&
931 key1->pk_len == key2->pk_len)
937 /* Copies the public key indicated by `public_key' and returns new allocated
938 public key which is indentical to the `public_key'. */
940 SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
942 SilcPublicKey key = silc_calloc(1, sizeof(*key));
946 key->len = public_key->len;
947 key->name = silc_memdup(public_key->name, strlen(public_key->name));
948 key->identifier = silc_memdup(public_key->identifier,
949 strlen(public_key->identifier));
950 key->pk = silc_memdup(public_key->pk, public_key->pk_len);
951 key->pk_len = public_key->pk_len;
952 key->pk_type = public_key->pk_type;
957 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
960 silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
962 return silc_pkcs_private_key_data_encode(private_key->prv,
963 private_key->prv_len,
964 private_key->name, len);
967 /* Encodes SILC private key. Returns the encoded data. */
970 silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
971 char *pkcs, SilcUInt32 *len)
977 totlen = 2 + strlen(pkcs) + prv_len;
978 buf = silc_buffer_alloc_size(totlen);
982 silc_buffer_format(buf,
983 SILC_STR_UI_SHORT(strlen(pkcs)),
984 SILC_STR_UI32_STRING(pkcs),
985 SILC_STR_UI_XNSTRING(prv, prv_len),
988 ret = silc_buffer_steal(buf, len);
989 silc_buffer_free(buf);
993 /* Decodes SILC style private key. Returns TRUE if the decoding was
994 successful. Allocates new private key as well. */
996 SilcBool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
997 SilcPrivateKey *private_key)
999 SilcBufferStruct buf;
1001 SilcUInt16 pkcs_len;
1003 unsigned char *pkcs_name = NULL, *key_data = NULL;
1006 silc_buffer_set(&buf, data, data_len);
1008 /* Get algorithm name and identifier */
1010 silc_buffer_unformat(&buf,
1011 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
1014 SILC_LOG_DEBUG(("Cannot decode private key buffer"));
1018 if (pkcs_len < 1 || pkcs_len > silc_buffer_truelen(&buf)) {
1019 SILC_LOG_DEBUG(("Malformed private key buffer"));
1023 /* See if we support this algorithm (check only if PKCS are registered). */
1024 if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
1025 SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
1029 /* Get key data. We assume that rest of the buffer is key data. */
1030 silc_buffer_pull(&buf, 2 + pkcs_len);
1031 key_len = silc_buffer_len(&buf);
1032 ret = silc_buffer_unformat(&buf,
1033 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
1038 /* Try to set the key. If this fails the key must be malformed. This
1039 code assumes that the PKCS routine checks the format of the key.
1040 (check only if PKCS are registered) */
1041 if (SILC_PKCS_LIST) {
1042 silc_pkcs_alloc(pkcs_name, SILC_PKCS_SILC, &alg);
1043 if (!alg->pkcs->set_private_key(alg->context, key_data, key_len)) {
1044 SILC_LOG_DEBUG(("Could not set private key data"));
1047 silc_pkcs_free(alg);
1051 *private_key = silc_calloc(1, sizeof(**private_key));
1052 (*private_key)->name = pkcs_name;
1053 (*private_key)->prv = key_data;
1054 (*private_key)->prv_len = key_len;
1060 silc_free(pkcs_name);
1061 silc_free(key_data);
1065 /* Internal routine to save public key */
1067 static SilcBool silc_pkcs_save_public_key_internal(const char *filename,
1068 unsigned char *data,
1069 SilcUInt32 data_len,
1070 SilcUInt32 encoding)
1074 unsigned char *tmp = NULL;
1077 case SILC_PKCS_FILE_BIN:
1079 case SILC_PKCS_FILE_PEM:
1080 tmp = data = silc_pem_encode_file(data, data_len);
1081 data_len = strlen(data);
1085 len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1086 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1087 buf = silc_buffer_alloc_size(len);
1093 silc_buffer_format(buf,
1094 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
1095 SILC_STR_UI_XNSTRING(data, data_len),
1096 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
1099 /* Save into file */
1100 if (silc_file_writefile(filename, buf->data, silc_buffer_len(buf))) {
1102 silc_buffer_free(buf);
1107 silc_buffer_free(buf);
1111 /* Saves public key into file */
1113 SilcBool silc_pkcs_save_public_key(const char *filename, SilcPublicKey public_key,
1114 SilcUInt32 encoding)
1116 unsigned char *data;
1117 SilcUInt32 data_len;
1120 data = silc_pkcs_public_key_encode(public_key, &data_len);
1121 ret = silc_pkcs_save_public_key_internal(filename, data, data_len,
1127 /* Saves public key into file */
1129 SilcBool silc_pkcs_save_public_key_data(const char *filename, unsigned char *data,
1130 SilcUInt32 data_len, SilcUInt32 encoding)
1132 return silc_pkcs_save_public_key_internal(filename, data, data_len,
1136 #define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
1138 /* Internal routine to save private key. */
1140 static SilcBool silc_pkcs_save_private_key_internal(const char *filename,
1141 unsigned char *data,
1142 SilcUInt32 data_len,
1145 SilcUInt32 encoding)
1150 SilcBuffer buf, enc;
1151 SilcUInt32 len, blocklen, padlen;
1152 unsigned char tmp[32], keymat[64];
1155 memset(tmp, 0, sizeof(tmp));
1156 memset(keymat, 0, sizeof(keymat));
1158 /* Allocate the AES cipher */
1159 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1160 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1163 blocklen = silc_cipher_get_block_len(aes);
1164 if (blocklen * 2 > sizeof(tmp))
1167 /* Allocate SHA1 hash */
1168 if (!silc_hash_alloc("sha1", &sha1)) {
1169 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1170 silc_cipher_free(aes);
1175 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1176 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1177 silc_hash_free(sha1);
1178 silc_cipher_free(aes);
1182 /* Derive the encryption key from the provided key material. The key
1183 is 256 bits length, and derived by taking hash of the data, then
1184 re-hashing the data and the previous digest, and using the first and
1185 second digest as the key. */
1186 silc_hash_init(sha1);
1187 silc_hash_update(sha1, key, key_len);
1188 silc_hash_final(sha1, keymat);
1189 silc_hash_init(sha1);
1190 silc_hash_update(sha1, key, key_len);
1191 silc_hash_update(sha1, keymat, 16);
1192 silc_hash_final(sha1, keymat + 16);
1194 /* Set the key to the cipher */
1195 silc_cipher_set_key(aes, keymat, 256);
1197 /* Encode the buffer to be encrypted. Add padding to it too, at least
1198 block size of the cipher. */
1200 /* Allocate buffer for encryption */
1201 len = silc_hmac_len(sha1hmac);
1202 padlen = 16 + (16 - ((data_len + 4) % blocklen));
1203 enc = silc_buffer_alloc_size(4 + 4 + data_len + padlen + len);
1205 silc_hmac_free(sha1hmac);
1206 silc_hash_free(sha1);
1207 silc_cipher_free(aes);
1211 /* Generate padding */
1212 for (i = 0; i < padlen; i++)
1213 tmp[i] = silc_rng_global_get_byte_fast();
1215 /* Put magic number */
1216 SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
1217 silc_buffer_pull(enc, 4);
1219 /* Encode the buffer */
1220 silc_buffer_format(enc,
1221 SILC_STR_UI_INT(data_len),
1222 SILC_STR_UI_XNSTRING(data, data_len),
1223 SILC_STR_UI_XNSTRING(tmp, padlen),
1227 silc_cipher_encrypt(aes, enc->data, enc->data, silc_buffer_len(enc) - len,
1228 silc_cipher_get_iv(aes));
1230 silc_buffer_push(enc, 4);
1232 /* Compute HMAC over the encrypted data and append the MAC to data.
1233 The key is the first digest of the original key material. */
1234 data_len = silc_buffer_len(enc) - len;
1235 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1236 silc_hmac_update(sha1hmac, enc->data, data_len);
1237 silc_buffer_pull(enc, data_len);
1238 silc_hmac_final(sha1hmac, enc->data, NULL);
1239 silc_buffer_push(enc, data_len);
1242 memset(keymat, 0, sizeof(keymat));
1243 memset(tmp, 0, sizeof(tmp));
1244 silc_hmac_free(sha1hmac);
1245 silc_hash_free(sha1);
1246 silc_cipher_free(aes);
1249 data_len = silc_buffer_len(enc);
1252 case SILC_PKCS_FILE_BIN:
1254 case SILC_PKCS_FILE_PEM:
1255 data = silc_pem_encode_file(data, data_len);
1256 data_len = strlen(data);
1260 /* Encode the data and save to file */
1261 len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1262 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1263 buf = silc_buffer_alloc_size(len);
1264 silc_buffer_format(buf,
1265 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
1266 SILC_STR_UI_XNSTRING(data, data_len),
1267 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
1270 /* Save into a file */
1271 if (silc_file_writefile_mode(filename, buf->data,
1272 silc_buffer_len(buf), 0600)) {
1273 silc_buffer_clear(buf);
1274 silc_buffer_free(buf);
1275 silc_buffer_clear(enc);
1276 silc_buffer_free(enc);
1280 silc_buffer_clear(buf);
1281 silc_buffer_free(buf);
1282 silc_buffer_clear(enc);
1283 silc_buffer_free(enc);
1287 /* Saves private key into file. */
1289 SilcBool silc_pkcs_save_private_key(const char *filename,
1290 SilcPrivateKey private_key,
1291 unsigned char *passphrase,
1292 SilcUInt32 passphrase_len,
1293 SilcUInt32 encoding)
1295 unsigned char *data;
1296 SilcUInt32 data_len;
1299 data = silc_pkcs_private_key_encode(private_key, &data_len);
1300 ret = silc_pkcs_save_private_key_internal(filename, data, data_len,
1301 passphrase, passphrase_len,
1303 memset(data, 0, data_len);
1308 /* Loads public key from file and allocates new public key. Returns TRUE
1309 if loading was successful. */
1311 SilcBool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key,
1312 SilcUInt32 encoding)
1314 unsigned char *cp, *old, *data, byte;
1315 SilcUInt32 i, data_len, len;
1317 SILC_LOG_DEBUG(("Loading public key `%s' with %s encoding", filename,
1318 encoding == SILC_PKCS_FILE_PEM ? "Base64" :
1319 encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
1321 old = data = silc_file_readfile(filename, &data_len);
1325 /* Check start of file and remove header from the data. */
1326 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
1328 for (i = 0; i < len; i++) {
1331 if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
1332 memset(old, 0, data_len);
1339 /* Decode public key */
1341 len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1342 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1345 case SILC_PKCS_FILE_BIN:
1347 case SILC_PKCS_FILE_PEM:
1348 data = silc_pem_decode(data, len, &len);
1349 memset(old, 0, data_len);
1356 if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
1357 memset(old, 0, data_len);
1363 memset(old, 0, data_len);
1368 /* Load private key from file and allocates new private key. Returns TRUE
1369 if loading was successful. */
1371 SilcBool silc_pkcs_load_private_key(const char *filename,
1372 SilcPrivateKey *private_key,
1373 unsigned char *passphrase,
1374 SilcUInt32 passphrase_len,
1375 SilcUInt32 encoding)
1380 SilcUInt32 blocklen;
1381 unsigned char tmp[32], keymat[64];
1382 unsigned char *cp, *old, *data, byte;
1383 SilcUInt32 i, data_len, len, magic, mac_len;
1385 SILC_LOG_DEBUG(("Loading private key `%s' with %s encoding", filename,
1386 encoding == SILC_PKCS_FILE_PEM ? "Base64" :
1387 encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
1389 old = data = silc_file_readfile(filename, &data_len);
1393 /* Check start of file and remove header from the data. */
1394 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
1396 for (i = 0; i < len; i++) {
1399 if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
1400 memset(old, 0, data_len);
1407 /* Decode private key */
1408 len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1409 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1412 case SILC_PKCS_FILE_BIN:
1414 case SILC_PKCS_FILE_PEM:
1415 data = silc_pem_decode(data, len, &len);
1417 memset(old, 0, data_len);
1424 memset(tmp, 0, sizeof(tmp));
1425 memset(keymat, 0, sizeof(keymat));
1427 /* Private key files without the specific magic number are assumed
1428 to be the old-style private keys that are not encrypted. */
1429 SILC_GET32_MSB(magic, data);
1430 if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
1431 SILC_LOG_DEBUG(("Private key does not have correct magic!"));
1433 /* Now decode the actual private key */
1434 if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1435 memset(old, 0, data_len);
1440 memset(old, 0, data_len);
1445 /* Allocate the AES cipher */
1446 if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
1447 SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
1448 memset(old, 0, data_len);
1452 blocklen = silc_cipher_get_block_len(aes);
1453 if (blocklen * 2 > sizeof(tmp)) {
1454 memset(old, 0, data_len);
1459 /* Allocate SHA1 hash */
1460 if (!silc_hash_alloc("sha1", &sha1)) {
1461 SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
1462 silc_cipher_free(aes);
1463 memset(old, 0, data_len);
1469 if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
1470 SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
1471 silc_hash_free(sha1);
1472 silc_cipher_free(aes);
1473 memset(old, 0, data_len);
1478 /* Derive the decryption key from the provided key material. The key
1479 is 256 bits length, and derived by taking hash of the data, then
1480 re-hashing the data and the previous digest, and using the first and
1481 second digest as the key. */
1482 silc_hash_init(sha1);
1483 silc_hash_update(sha1, passphrase, passphrase_len);
1484 silc_hash_final(sha1, keymat);
1485 silc_hash_init(sha1);
1486 silc_hash_update(sha1, passphrase, passphrase_len);
1487 silc_hash_update(sha1, keymat, 16);
1488 silc_hash_final(sha1, keymat + 16);
1490 /* Set the key to the cipher */
1491 silc_cipher_set_key(aes, keymat, 256);
1493 /* First, verify the MAC of the private key data */
1494 mac_len = silc_hmac_len(sha1hmac);
1495 silc_hmac_init_with_key(sha1hmac, keymat, 16);
1496 silc_hmac_update(sha1hmac, data, len - mac_len);
1497 silc_hmac_final(sha1hmac, tmp, NULL);
1498 if (memcmp(tmp, data + (len - mac_len), mac_len)) {
1499 SILC_LOG_DEBUG(("Integrity check for private key failed"));
1500 memset(keymat, 0, sizeof(keymat));
1501 memset(tmp, 0, sizeof(tmp));
1502 silc_hmac_free(sha1hmac);
1503 silc_hash_free(sha1);
1504 silc_cipher_free(aes);
1505 memset(old, 0, data_len);
1512 /* Decrypt the private key buffer */
1513 silc_cipher_decrypt(aes, data, data, len - mac_len, NULL);
1514 SILC_GET32_MSB(i, data);
1516 SILC_LOG_DEBUG(("Bad private key length in buffer!"));
1517 memset(keymat, 0, sizeof(keymat));
1518 memset(tmp, 0, sizeof(tmp));
1519 silc_hmac_free(sha1hmac);
1520 silc_hash_free(sha1);
1521 silc_cipher_free(aes);
1522 memset(old, 0, data_len);
1530 memset(keymat, 0, sizeof(keymat));
1531 memset(tmp, 0, sizeof(tmp));
1532 silc_hmac_free(sha1hmac);
1533 silc_hash_free(sha1);
1534 silc_cipher_free(aes);
1536 /* Now decode the actual private key */
1537 if (!silc_pkcs_private_key_decode(data, len, private_key)) {
1538 memset(old, 0, data_len);
1543 memset(old, 0, data_len);