5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "silcincludes.h"
27 /* Dynamically registered list of PKCS. */
28 SilcDList silc_pkcs_list = NULL;
30 /* Static list of PKCS for silc_pkcs_register_default(). */
31 SilcPKCSObject silc_default_pkcs[] =
33 /* RSA with PKCS #1 (Uses directly routines from Raw RSA operations) */
35 silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
36 silc_rsa_get_private_key, silc_rsa_set_public_key,
37 silc_rsa_set_private_key, silc_rsa_context_len,
38 silc_pkcs1_encrypt, silc_pkcs1_decrypt,
39 silc_pkcs1_sign, silc_pkcs1_verify },
41 /* Raw RSA operations */
43 silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
44 silc_rsa_get_private_key, silc_rsa_set_public_key,
45 silc_rsa_set_private_key, silc_rsa_context_len,
46 silc_rsa_encrypt, silc_rsa_decrypt,
47 silc_rsa_sign, silc_rsa_verify },
49 { NULL, NULL, NULL, NULL, NULL,
50 NULL, NULL, NULL, NULL, NULL, NULL }
53 /* Register a new PKCS into SILC. This is used at the initialization of
56 bool silc_pkcs_register(SilcPKCSObject *pkcs)
60 SILC_LOG_DEBUG(("Registering new PKCS `%s'", pkcs->name));
62 new = silc_calloc(1, sizeof(*new));
63 new->name = strdup(pkcs->name);
64 new->init = pkcs->init;
65 new->clear_keys = pkcs->clear_keys;
66 new->get_public_key = pkcs->get_public_key;
67 new->get_private_key = pkcs->get_private_key;
68 new->set_public_key = pkcs->set_public_key;
69 new->set_private_key = pkcs->set_private_key;
70 new->context_len = pkcs->context_len;
71 new->encrypt = pkcs->encrypt;
72 new->decrypt = pkcs->decrypt;
73 new->sign = pkcs->sign;
74 new->verify = pkcs->verify;
77 if (silc_pkcs_list == NULL)
78 silc_pkcs_list = silc_dlist_init();
79 silc_dlist_add(silc_pkcs_list, new);
84 /* Unregister a PKCS from the SILC. */
86 bool silc_pkcs_unregister(SilcPKCSObject *pkcs)
88 SilcPKCSObject *entry;
90 SILC_LOG_DEBUG(("Unregistering PKCS"));
95 silc_dlist_start(silc_pkcs_list);
96 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
97 if (pkcs == SILC_ALL_PKCS || entry == pkcs) {
98 silc_dlist_del(silc_pkcs_list, entry);
100 if (silc_dlist_count(silc_pkcs_list) == 0) {
101 silc_dlist_uninit(silc_pkcs_list);
102 silc_pkcs_list = NULL;
112 /* Function that registers all the default PKCS (all builtin PKCS).
113 The application may use this to register the default PKCS if specific
114 PKCS in any specific order is not wanted. */
116 bool silc_pkcs_register_default(void)
120 for (i = 0; silc_default_pkcs[i].name; i++)
121 silc_pkcs_register(&(silc_default_pkcs[i]));
126 /* Allocates a new SilcPKCS object. The new allocated object is returned
127 to the 'new_pkcs' argument. */
129 bool silc_pkcs_alloc(const unsigned char *name, SilcPKCS *new_pkcs)
131 SilcPKCSObject *entry;
133 SILC_LOG_DEBUG(("Allocating new PKCS object"));
135 if (silc_pkcs_list) {
136 silc_dlist_start(silc_pkcs_list);
137 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
138 if (!strcmp(entry->name, name)) {
139 *new_pkcs = silc_calloc(1, sizeof(**new_pkcs));
140 (*new_pkcs)->pkcs = entry;
141 (*new_pkcs)->context = silc_calloc(1, entry->context_len());
142 (*new_pkcs)->get_key_len = silc_pkcs_get_key_len;
151 /* Free's the PKCS object */
153 void silc_pkcs_free(SilcPKCS pkcs)
156 silc_free(pkcs->context);
160 /* Return TRUE if PKCS algorithm `name' is supported. */
162 int silc_pkcs_is_supported(const unsigned char *name)
164 SilcPKCSObject *entry;
166 if (silc_pkcs_list) {
167 silc_dlist_start(silc_pkcs_list);
168 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
169 if (!strcmp(entry->name, name))
177 /* Returns comma separated list of supported PKCS algorithms */
179 char *silc_pkcs_get_supported(void)
181 SilcPKCSObject *entry;
186 if (silc_pkcs_list) {
187 silc_dlist_start(silc_pkcs_list);
188 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
189 len += strlen(entry->name);
190 list = silc_realloc(list, len + 1);
192 memcpy(list + (len - strlen(entry->name)),
193 entry->name, strlen(entry->name));
194 memcpy(list + len, ",", 1);
204 /* Returns the length of the key */
206 uint32 silc_pkcs_get_key_len(SilcPKCS self)
208 return self->key_len;
211 /* Returns SILC style public key */
213 unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, uint32 *len)
215 return pkcs->pkcs->get_public_key(pkcs->context, len);
218 /* Returns SILC style private key */
220 unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, uint32 *len)
222 return pkcs->pkcs->get_private_key(pkcs->context, len);
225 /* Sets public key from SilcPublicKey. */
227 uint32 silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
229 pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
231 return pkcs->key_len;
234 /* Sets public key from data. */
236 uint32 silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
239 pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, pk, pk_len);
240 return pkcs->key_len;
243 /* Sets private key from SilcPrivateKey. */
245 int silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
247 return pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
248 private_key->prv_len);
251 /* Sets private key from data. */
253 int silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
256 return pkcs->pkcs->set_private_key(pkcs->context, prv, prv_len);
261 int silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, uint32 src_len,
262 unsigned char *dst, uint32 *dst_len)
264 return pkcs->pkcs->encrypt(pkcs->context, src, src_len, dst, dst_len);
269 int silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, uint32 src_len,
270 unsigned char *dst, uint32 *dst_len)
272 return pkcs->pkcs->decrypt(pkcs->context, src, src_len, dst, dst_len);
275 /* Generates signature */
277 int silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, uint32 src_len,
278 unsigned char *dst, uint32 *dst_len)
280 return pkcs->pkcs->sign(pkcs->context, src, src_len, dst, dst_len);
283 /* Verifies signature */
285 int silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
286 uint32 signature_len, unsigned char *data,
289 return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
293 /* Generates signature with hash. The hash is signed. */
295 int silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
296 unsigned char *src, uint32 src_len,
297 unsigned char *dst, uint32 *dst_len)
299 unsigned char hashr[32];
303 silc_hash_make(hash, src, src_len, hashr);
304 hash_len = hash->hash->hash_len;
306 SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
308 ret = pkcs->pkcs->sign(pkcs->context, hashr, hash_len, dst, dst_len);
309 memset(hashr, 0, sizeof(hashr));
314 /* Verifies signature with hash. The `data' is hashed and verified against
317 int silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
318 unsigned char *signature,
319 uint32 signature_len,
323 unsigned char hashr[32];
327 silc_hash_make(hash, data, data_len, hashr);
328 hash_len = hash->hash->hash_len;
330 SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
332 ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
334 memset(hashr, 0, sizeof(hashr));
339 /* Encodes and returns SILC public key identifier. If some of the
340 arguments is NULL those are not encoded into the identifier string.
341 Protocol says that at least username and host must be provided. */
343 char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
344 char *email, char *org, char *country)
348 uint32 len, tlen = 0;
350 if (!username || !host)
353 len = (username ? strlen(username) : 0) +
354 (host ? strlen(host) : 0) +
355 (realname ? strlen(realname) : 0) +
356 (email ? strlen(email) : 0) +
357 (org ? strlen(org) : 0) +
358 (country ? strlen(country) : 0);
363 len += 3 + 5 + 5 + 4 + 4 + 4;
364 buf = silc_buffer_alloc(len);
365 silc_buffer_pull_tail(buf, len);
368 silc_buffer_format(buf,
369 SILC_STR_UI32_STRING("UN="),
370 SILC_STR_UI32_STRING(username),
372 silc_buffer_pull(buf, 3 + strlen(username));
373 tlen = 3 + strlen(username);
377 silc_buffer_format(buf,
378 SILC_STR_UI32_STRING(", "),
379 SILC_STR_UI32_STRING("HN="),
380 SILC_STR_UI32_STRING(host),
382 silc_buffer_pull(buf, 5 + strlen(host));
383 tlen += 5 + strlen(host);
387 silc_buffer_format(buf,
388 SILC_STR_UI32_STRING(", "),
389 SILC_STR_UI32_STRING("RN="),
390 SILC_STR_UI32_STRING(realname),
392 silc_buffer_pull(buf, 5 + strlen(realname));
393 tlen += 5 + strlen(realname);
397 silc_buffer_format(buf,
398 SILC_STR_UI32_STRING(", "),
399 SILC_STR_UI32_STRING("E="),
400 SILC_STR_UI32_STRING(email),
402 silc_buffer_pull(buf, 4 + strlen(email));
403 tlen += 4 + strlen(email);
407 silc_buffer_format(buf,
408 SILC_STR_UI32_STRING(", "),
409 SILC_STR_UI32_STRING("O="),
410 SILC_STR_UI32_STRING(org),
412 silc_buffer_pull(buf, 4 + strlen(org));
413 tlen += 4 + strlen(org);
417 silc_buffer_format(buf,
418 SILC_STR_UI32_STRING(", "),
419 SILC_STR_UI32_STRING("C="),
420 SILC_STR_UI32_STRING(country),
422 silc_buffer_pull(buf, 4 + strlen(country));
423 tlen += 4 + strlen(country);
426 silc_buffer_push(buf, buf->data - buf->head);
427 identifier = silc_calloc(tlen + 1, sizeof(*identifier));
428 memcpy(identifier, buf->data, tlen);
429 silc_buffer_free(buf);
434 /* Decodes the provided `identifier' and returns allocated context for
437 SilcPublicKeyIdentifier silc_pkcs_decode_identifier(char *identifier)
439 SilcPublicKeyIdentifier ident;
443 ident = silc_calloc(1, sizeof(*ident));
447 len = strcspn(cp, ",");
448 if (len - 1 >= 0 && cp[len - 1] == '\\') {
451 len = strcspn(cp, ",") + len;
452 if (len - 1 >= 0 && cp[len - 1] != '\\')
457 item = silc_calloc(len + 1, sizeof(char));
458 memcpy(item, cp, len);
460 if (strstr(item, "UN="))
461 ident->username = strdup(item + strcspn(cp, "=") + 1);
462 else if (strstr(item, "HN="))
463 ident->host = strdup(item + strcspn(cp, "=") + 1);
464 else if (strstr(item, "RN="))
465 ident->realname = strdup(item + strcspn(cp, "=") + 1);
466 else if (strstr(item, "E="))
467 ident->email = strdup(item + strcspn(cp, "=") + 1);
468 else if (strstr(item, "O="))
469 ident->org = strdup(item + strcspn(cp, "=") + 1);
470 else if (strstr(item, "C="))
471 ident->country = strdup(item + strcspn(cp, "=") + 1);
486 /* Free's decoded public key identifier context. Call this to free the
487 context returned by the silc_pkcs_decode_identifier. */
489 void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier)
491 silc_free(identifier->username);
492 silc_free(identifier->host);
493 silc_free(identifier->realname);
494 silc_free(identifier->email);
495 silc_free(identifier->org);
496 silc_free(identifier->country);
497 silc_free(identifier);
500 /* Allocates SILC style public key formed from sent arguments. All data
503 SilcPublicKey silc_pkcs_public_key_alloc(char *name, char *identifier,
507 SilcPublicKey public_key;
509 public_key = silc_calloc(1, sizeof(*public_key));
510 public_key->len = 4 + 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
511 public_key->name = strdup(name);
512 public_key->identifier = strdup(identifier);
513 public_key->pk_len = pk_len;
514 public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
515 memcpy(public_key->pk, pk, pk_len);
520 /* Free's public key */
522 void silc_pkcs_public_key_free(SilcPublicKey public_key)
525 silc_free(public_key->name);
526 silc_free(public_key->identifier);
527 silc_free(public_key->pk);
528 silc_free(public_key);
532 /* Allocates SILC private key formed from sent arguments. All data is
535 SilcPrivateKey silc_pkcs_private_key_alloc(char *name, unsigned char *prv,
538 SilcPrivateKey private_key;
540 private_key = silc_calloc(1, sizeof(*private_key));
541 private_key->name = strdup(name);
542 private_key->prv_len = prv_len;
543 private_key->prv = silc_calloc(prv_len, sizeof(*private_key->prv));
544 memcpy(private_key->prv, prv, prv_len);
549 /* Free's private key */
551 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
554 silc_free(private_key->name);
555 silc_free(private_key->prv);
556 silc_free(private_key);
560 /* Encodes SILC style public key from SilcPublicKey. Returns the encoded
564 silc_pkcs_public_key_encode(SilcPublicKey public_key, uint32 *len)
569 buf = silc_buffer_alloc(public_key->len);
570 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
572 silc_buffer_format(buf,
573 SILC_STR_UI_INT(public_key->len),
574 SILC_STR_UI_SHORT(strlen(public_key->name)),
575 SILC_STR_UI32_STRING(public_key->name),
576 SILC_STR_UI_SHORT(strlen(public_key->identifier)),
577 SILC_STR_UI32_STRING(public_key->identifier),
578 SILC_STR_UI_XNSTRING(public_key->pk,
582 *len = public_key->len;
584 ret = silc_calloc(buf->len, sizeof(*ret));
585 memcpy(ret, buf->data, buf->len);
586 silc_buffer_free(buf);
591 /* Encodes SILC style public key. Returns the encoded data. */
594 silc_pkcs_public_key_data_encode(unsigned char *pk, uint32 pk_len,
595 char *pkcs, char *identifier,
602 totlen = 4 + 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
603 buf = silc_buffer_alloc(totlen);
604 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
606 silc_buffer_format(buf,
607 SILC_STR_UI_INT(totlen),
608 SILC_STR_UI_SHORT(strlen(pkcs)),
609 SILC_STR_UI32_STRING(pkcs),
610 SILC_STR_UI_SHORT(strlen(identifier)),
611 SILC_STR_UI32_STRING(identifier),
612 SILC_STR_UI_XNSTRING(pk, pk_len),
617 ret = silc_calloc(buf->len, sizeof(*ret));
618 memcpy(ret, buf->data, buf->len);
619 silc_buffer_free(buf);
624 /* Decodes SILC style public key. Returns TRUE if the decoding was
625 successful. Allocates new public key as well. */
627 int silc_pkcs_public_key_decode(unsigned char *data, uint32 data_len,
628 SilcPublicKey *public_key)
632 uint16 pkcs_len, identifier_len;
633 uint32 totlen, key_len;
634 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
637 buf = silc_buffer_alloc(data_len);
638 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
639 silc_buffer_put(buf, data, data_len);
642 ret = silc_buffer_unformat(buf,
643 SILC_STR_UI_INT(&totlen),
646 silc_buffer_free(buf);
650 if (totlen != data_len) {
651 silc_buffer_free(buf);
655 /* Get algorithm name and identifier */
656 silc_buffer_pull(buf, 4);
658 silc_buffer_unformat(buf,
659 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
660 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
665 if (pkcs_len < 1 || identifier_len < 3 ||
666 pkcs_len + identifier_len > totlen)
669 /* See if we support this algorithm (check only if PKCS are registered) */
670 if (silc_pkcs_list && !silc_pkcs_is_supported(pkcs_name)) {
671 SILC_LOG_DEBUG(("Unknown PKCS %s", pkcs_name));
675 /* Protocol says that at least UN and HN must be provided as identifier,
677 if (!strstr(ident, "UN=") && !strstr(ident, "HN=")) {
678 SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
683 /* Get key data. We assume that rest of the buffer is key data. */
684 silc_buffer_pull(buf, 2 + pkcs_len + 2 + identifier_len);
686 ret = silc_buffer_unformat(buf,
687 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
692 /* Try to set the key. If this fails the key must be malformed. This
693 code assumes that the PKCS routine checks the format of the key.
694 (check only if PKCS are registered) */
695 if (silc_pkcs_list) {
696 silc_pkcs_alloc(pkcs_name, &alg);
697 if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
703 *public_key = silc_calloc(1, sizeof(**public_key));
704 (*public_key)->len = totlen;
705 (*public_key)->name = pkcs_name;
706 (*public_key)->identifier = ident;
707 (*public_key)->pk = key_data;
708 (*public_key)->pk_len = key_len;
711 silc_buffer_free(buf);
716 silc_free(pkcs_name);
721 silc_buffer_free(buf);
725 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
728 silc_pkcs_private_key_encode(SilcPrivateKey private_key, uint32 *len)
734 totlen = 2 + strlen(private_key->name) + private_key->prv_len;
735 buf = silc_buffer_alloc(totlen);
736 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
738 silc_buffer_format(buf,
739 SILC_STR_UI_SHORT(strlen(private_key->name)),
740 SILC_STR_UI32_STRING(private_key->name),
741 SILC_STR_UI_XNSTRING(private_key->prv,
742 private_key->prv_len),
747 ret = silc_calloc(buf->len, sizeof(*ret));
748 memcpy(ret, buf->data, buf->len);
749 silc_buffer_free(buf);
754 /* Encodes SILC private key. Returns the encoded data. */
757 silc_pkcs_private_key_data_encode(unsigned char *prv, uint32 prv_len,
758 char *pkcs, uint32 *len)
764 totlen = 2 + strlen(pkcs) + prv_len;
765 buf = silc_buffer_alloc(totlen);
766 silc_buffer_pull_tail(buf, totlen);
768 silc_buffer_format(buf,
769 SILC_STR_UI_SHORT(strlen(pkcs)),
770 SILC_STR_UI32_STRING(pkcs),
771 SILC_STR_UI_XNSTRING(prv, prv_len),
776 ret = silc_calloc(buf->len, sizeof(*ret));
777 memcpy(ret, buf->data, buf->len);
778 silc_buffer_free(buf);
783 /* Decodes SILC style public key. Returns TRUE if the decoding was
784 successful. Allocates new private key as well. */
786 int silc_pkcs_private_key_decode(unsigned char *data, uint32 data_len,
787 SilcPrivateKey *private_key)
793 unsigned char *pkcs_name = NULL, *key_data = NULL;
796 buf = silc_buffer_alloc(data_len);
797 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
798 silc_buffer_put(buf, data, data_len);
800 /* Get algorithm name and identifier */
802 silc_buffer_unformat(buf,
803 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
808 if (pkcs_len < 1 || pkcs_len > buf->truelen)
811 /* See if we support this algorithm (check only if PKCS are registered). */
812 if (silc_pkcs_list && !silc_pkcs_is_supported(pkcs_name)) {
813 SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
817 /* Get key data. We assume that rest of the buffer is key data. */
818 silc_buffer_pull(buf, 2 + pkcs_len);
820 ret = silc_buffer_unformat(buf,
821 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
826 /* Try to set the key. If this fails the key must be malformed. This
827 code assumes that the PKCS routine checks the format of the key.
828 (check only if PKCS are registered) */
829 if (silc_pkcs_list) {
830 silc_pkcs_alloc(pkcs_name, &alg);
831 if (!alg->pkcs->set_private_key(alg->context, key_data, key_len))
837 *private_key = silc_calloc(1, sizeof(**private_key));
838 (*private_key)->name = pkcs_name;
839 (*private_key)->prv = key_data;
840 (*private_key)->prv_len = key_len;
843 silc_buffer_free(buf);
848 silc_free(pkcs_name);
851 silc_buffer_free(buf);
855 /* Internal routine to save public key */
857 static int silc_pkcs_save_public_key_internal(char *filename,
866 case SILC_PKCS_FILE_BIN:
868 case SILC_PKCS_FILE_PEM:
869 data = silc_encode_pem_file(data, data_len);
870 data_len = strlen(data);
874 len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
875 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
876 buf = silc_buffer_alloc(len);
877 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
879 silc_buffer_format(buf,
880 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
881 SILC_STR_UI_XNSTRING(data, data_len),
882 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
886 if (silc_file_write(filename, buf->data, buf->len)) {
887 silc_buffer_free(buf);
891 silc_buffer_free(buf);
895 /* Saves public key into file */
897 int silc_pkcs_save_public_key(char *filename, SilcPublicKey public_key,
903 data = silc_pkcs_public_key_encode(public_key, &data_len);
904 return silc_pkcs_save_public_key_internal(filename, data, data_len,
908 /* Saves public key into file */
910 int silc_pkcs_save_public_key_data(char *filename, unsigned char *data,
914 return silc_pkcs_save_public_key_internal(filename, data, data_len,
918 /* Internal routine to save private key. */
920 static int silc_pkcs_save_private_key_internal(char *filename,
929 case SILC_PKCS_FILE_BIN:
931 case SILC_PKCS_FILE_PEM:
932 data = silc_encode_pem_file(data, data_len);
933 data_len = strlen(data);
937 len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
938 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
939 buf = silc_buffer_alloc(len);
940 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
942 silc_buffer_format(buf,
943 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
944 SILC_STR_UI_XNSTRING(data, data_len),
945 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
948 /* Save into a file */
949 if (silc_file_write_mode(filename, buf->data, buf->len, 0600)) {
950 silc_buffer_free(buf);
954 silc_buffer_free(buf);
958 /* Saves private key into file. */
959 /* XXX The buffer should be encrypted if passphrase is provided. */
961 int silc_pkcs_save_private_key(char *filename, SilcPrivateKey private_key,
962 unsigned char *passphrase,
968 data = silc_pkcs_private_key_encode(private_key, &data_len);
969 return silc_pkcs_save_private_key_internal(filename, data, data_len,
973 /* Saves private key into file. */
974 /* XXX The buffer should be encrypted if passphrase is provided. */
976 int silc_pkcs_save_private_key_data(char *filename, unsigned char *data,
978 unsigned char *passphrase,
981 return silc_pkcs_save_private_key_internal(filename, data, data_len,
985 /* Loads public key from file and allocates new public key. Returns TRUE
986 is loading was successful. */
988 int silc_pkcs_load_public_key(char *filename, SilcPublicKey *public_key,
991 unsigned char *cp, *old, *data, byte;
992 uint32 i, data_len, len;
994 old = data = silc_file_read(filename, &data_len);
998 /* Check start of file and remove header from the data. */
999 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
1001 for (i = 0; i < len; i++) {
1004 if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
1005 memset(old, 0, data_len);
1012 /* Decode public key */
1014 len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1015 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1018 case SILC_PKCS_FILE_BIN:
1020 case SILC_PKCS_FILE_PEM:
1021 data = silc_decode_pem(data, len, &len);
1025 if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
1026 memset(old, 0, data_len);
1032 memset(old, 0, data_len);
1037 /* Load private key from file and allocates new private key. Returns TRUE
1038 if loading was successful. */
1039 /* XXX Should support encrypted private key files */
1041 int silc_pkcs_load_private_key(char *filename, SilcPrivateKey *private_key,
1044 unsigned char *cp, *old, *data, byte;
1045 uint32 i, data_len, len;
1047 old = data = silc_file_read(filename, &data_len);
1051 /* Check start of file and remove header from the data. */
1052 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
1054 for (i = 0; i < len; i++) {
1057 if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
1058 memset(old, 0, data_len);
1065 /* Decode private key */
1067 len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1068 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1071 case SILC_PKCS_FILE_BIN:
1073 case SILC_PKCS_FILE_PEM:
1074 data = silc_decode_pem(data, len, &len);
1078 if (!data || !silc_pkcs_private_key_decode(data, len, private_key)) {
1079 memset(old, 0, data_len);
1085 memset(old, 0, data_len);