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 item = silc_calloc(len + 1, sizeof(char));
449 memcpy(item, cp, len);
451 if (strstr(item, "UN="))
452 ident->username = strdup(item + 3);
453 else if (strstr(item, "HN="))
454 ident->host = strdup(item + 3);
455 else if (strstr(item, "RN="))
456 ident->realname = strdup(item + 3);
457 else if (strstr(item, "E="))
458 ident->email = strdup(item + 2);
459 else if (strstr(item, "O="))
460 ident->org = strdup(item + 2);
461 else if (strstr(item, "C="))
462 ident->country = strdup(item + 2);
477 /* Free's decoded public key identifier context. Call this to free the
478 context returned by the silc_pkcs_decode_identifier. */
480 void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier)
482 silc_free(identifier->username);
483 silc_free(identifier->host);
484 silc_free(identifier->realname);
485 silc_free(identifier->email);
486 silc_free(identifier->org);
487 silc_free(identifier->country);
488 silc_free(identifier);
491 /* Allocates SILC style public key formed from sent arguments. All data
494 SilcPublicKey silc_pkcs_public_key_alloc(char *name, char *identifier,
498 SilcPublicKey public_key;
500 public_key = silc_calloc(1, sizeof(*public_key));
501 public_key->len = 4 + 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
502 public_key->name = strdup(name);
503 public_key->identifier = strdup(identifier);
504 public_key->pk_len = pk_len;
505 public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
506 memcpy(public_key->pk, pk, pk_len);
511 /* Free's public key */
513 void silc_pkcs_public_key_free(SilcPublicKey public_key)
516 silc_free(public_key->name);
517 silc_free(public_key->identifier);
518 silc_free(public_key->pk);
519 silc_free(public_key);
523 /* Allocates SILC private key formed from sent arguments. All data is
526 SilcPrivateKey silc_pkcs_private_key_alloc(char *name, unsigned char *prv,
529 SilcPrivateKey private_key;
531 private_key = silc_calloc(1, sizeof(*private_key));
532 private_key->name = strdup(name);
533 private_key->prv_len = prv_len;
534 private_key->prv = silc_calloc(prv_len, sizeof(*private_key->prv));
535 memcpy(private_key->prv, prv, prv_len);
540 /* Free's private key */
542 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
545 silc_free(private_key->name);
546 silc_free(private_key->prv);
547 silc_free(private_key);
551 /* Encodes SILC style public key from SilcPublicKey. Returns the encoded
555 silc_pkcs_public_key_encode(SilcPublicKey public_key, uint32 *len)
560 buf = silc_buffer_alloc(public_key->len);
561 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
563 silc_buffer_format(buf,
564 SILC_STR_UI_INT(public_key->len),
565 SILC_STR_UI_SHORT(strlen(public_key->name)),
566 SILC_STR_UI32_STRING(public_key->name),
567 SILC_STR_UI_SHORT(strlen(public_key->identifier)),
568 SILC_STR_UI32_STRING(public_key->identifier),
569 SILC_STR_UI_XNSTRING(public_key->pk,
573 *len = public_key->len;
575 ret = silc_calloc(buf->len, sizeof(*ret));
576 memcpy(ret, buf->data, buf->len);
577 silc_buffer_free(buf);
582 /* Encodes SILC style public key. Returns the encoded data. */
585 silc_pkcs_public_key_data_encode(unsigned char *pk, uint32 pk_len,
586 char *pkcs, char *identifier,
593 totlen = 4 + 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
594 buf = silc_buffer_alloc(totlen);
595 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
597 silc_buffer_format(buf,
598 SILC_STR_UI_INT(totlen),
599 SILC_STR_UI_SHORT(strlen(pkcs)),
600 SILC_STR_UI32_STRING(pkcs),
601 SILC_STR_UI_SHORT(strlen(identifier)),
602 SILC_STR_UI32_STRING(identifier),
603 SILC_STR_UI_XNSTRING(pk, pk_len),
608 ret = silc_calloc(buf->len, sizeof(*ret));
609 memcpy(ret, buf->data, buf->len);
610 silc_buffer_free(buf);
615 /* Decodes SILC style public key. Returns TRUE if the decoding was
616 successful. Allocates new public key as well. */
618 int silc_pkcs_public_key_decode(unsigned char *data, uint32 data_len,
619 SilcPublicKey *public_key)
623 uint16 pkcs_len, identifier_len;
624 uint32 totlen, key_len;
625 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
628 buf = silc_buffer_alloc(data_len);
629 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
630 silc_buffer_put(buf, data, data_len);
633 ret = silc_buffer_unformat(buf,
634 SILC_STR_UI_INT(&totlen),
637 silc_buffer_free(buf);
641 if (totlen != data_len) {
642 silc_buffer_free(buf);
646 /* Get algorithm name and identifier */
647 silc_buffer_pull(buf, 4);
649 silc_buffer_unformat(buf,
650 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
651 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
656 if (pkcs_len < 1 || identifier_len < 3 ||
657 pkcs_len + identifier_len > totlen)
660 /* See if we support this algorithm (check only if PKCS are registered) */
661 if (silc_pkcs_list && !silc_pkcs_is_supported(pkcs_name)) {
662 SILC_LOG_DEBUG(("Unknown PKCS %s", pkcs_name));
666 /* Protocol says that at least UN and HN must be provided as identifier,
668 if (!strstr(ident, "UN=") && !strstr(ident, "HN=")) {
669 SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
674 /* Get key data. We assume that rest of the buffer is key data. */
675 silc_buffer_pull(buf, 2 + pkcs_len + 2 + identifier_len);
677 ret = silc_buffer_unformat(buf,
678 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
683 /* Try to set the key. If this fails the key must be malformed. This
684 code assumes that the PKCS routine checks the format of the key.
685 (check only if PKCS are registered) */
686 if (silc_pkcs_list) {
687 silc_pkcs_alloc(pkcs_name, &alg);
688 if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
694 *public_key = silc_calloc(1, sizeof(**public_key));
695 (*public_key)->len = totlen;
696 (*public_key)->name = pkcs_name;
697 (*public_key)->identifier = ident;
698 (*public_key)->pk = key_data;
699 (*public_key)->pk_len = key_len;
702 silc_buffer_free(buf);
707 silc_free(pkcs_name);
712 silc_buffer_free(buf);
716 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
719 silc_pkcs_private_key_encode(SilcPrivateKey private_key, uint32 *len)
725 totlen = 2 + strlen(private_key->name) + private_key->prv_len;
726 buf = silc_buffer_alloc(totlen);
727 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
729 silc_buffer_format(buf,
730 SILC_STR_UI_SHORT(strlen(private_key->name)),
731 SILC_STR_UI32_STRING(private_key->name),
732 SILC_STR_UI_XNSTRING(private_key->prv,
733 private_key->prv_len),
738 ret = silc_calloc(buf->len, sizeof(*ret));
739 memcpy(ret, buf->data, buf->len);
740 silc_buffer_free(buf);
745 /* Encodes SILC private key. Returns the encoded data. */
748 silc_pkcs_private_key_data_encode(unsigned char *prv, uint32 prv_len,
749 char *pkcs, uint32 *len)
755 totlen = 2 + strlen(pkcs) + prv_len;
756 buf = silc_buffer_alloc(totlen);
757 silc_buffer_pull_tail(buf, totlen);
759 silc_buffer_format(buf,
760 SILC_STR_UI_SHORT(strlen(pkcs)),
761 SILC_STR_UI32_STRING(pkcs),
762 SILC_STR_UI_XNSTRING(prv, prv_len),
767 ret = silc_calloc(buf->len, sizeof(*ret));
768 memcpy(ret, buf->data, buf->len);
769 silc_buffer_free(buf);
774 /* Decodes SILC style public key. Returns TRUE if the decoding was
775 successful. Allocates new private key as well. */
777 int silc_pkcs_private_key_decode(unsigned char *data, uint32 data_len,
778 SilcPrivateKey *private_key)
784 unsigned char *pkcs_name = NULL, *key_data = NULL;
787 buf = silc_buffer_alloc(data_len);
788 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
789 silc_buffer_put(buf, data, data_len);
791 /* Get algorithm name and identifier */
793 silc_buffer_unformat(buf,
794 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
799 if (pkcs_len < 1 || pkcs_len > buf->truelen)
802 /* See if we support this algorithm (check only if PKCS are registered). */
803 if (silc_pkcs_list && !silc_pkcs_is_supported(pkcs_name)) {
804 SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
808 /* Get key data. We assume that rest of the buffer is key data. */
809 silc_buffer_pull(buf, 2 + pkcs_len);
811 ret = silc_buffer_unformat(buf,
812 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
817 /* Try to set the key. If this fails the key must be malformed. This
818 code assumes that the PKCS routine checks the format of the key.
819 (check only if PKCS are registered) */
820 if (silc_pkcs_list) {
821 silc_pkcs_alloc(pkcs_name, &alg);
822 if (!alg->pkcs->set_private_key(alg->context, key_data, key_len))
828 *private_key = silc_calloc(1, sizeof(**private_key));
829 (*private_key)->name = pkcs_name;
830 (*private_key)->prv = key_data;
831 (*private_key)->prv_len = key_len;
834 silc_buffer_free(buf);
839 silc_free(pkcs_name);
842 silc_buffer_free(buf);
846 /* Internal routine to save public key */
848 static int silc_pkcs_save_public_key_internal(char *filename,
857 case SILC_PKCS_FILE_BIN:
859 case SILC_PKCS_FILE_PEM:
860 data = silc_encode_pem_file(data, data_len);
861 data_len = strlen(data);
865 len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
866 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
867 buf = silc_buffer_alloc(len);
868 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
870 silc_buffer_format(buf,
871 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
872 SILC_STR_UI_XNSTRING(data, data_len),
873 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
877 if (silc_file_write(filename, buf->data, buf->len)) {
878 silc_buffer_free(buf);
882 silc_buffer_free(buf);
886 /* Saves public key into file */
888 int silc_pkcs_save_public_key(char *filename, SilcPublicKey public_key,
894 data = silc_pkcs_public_key_encode(public_key, &data_len);
895 return silc_pkcs_save_public_key_internal(filename, data, data_len,
899 /* Saves public key into file */
901 int silc_pkcs_save_public_key_data(char *filename, unsigned char *data,
905 return silc_pkcs_save_public_key_internal(filename, data, data_len,
909 /* Internal routine to save private key. */
911 static int silc_pkcs_save_private_key_internal(char *filename,
920 case SILC_PKCS_FILE_BIN:
922 case SILC_PKCS_FILE_PEM:
923 data = silc_encode_pem_file(data, data_len);
924 data_len = strlen(data);
928 len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
929 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
930 buf = silc_buffer_alloc(len);
931 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
933 silc_buffer_format(buf,
934 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
935 SILC_STR_UI_XNSTRING(data, data_len),
936 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
939 /* Save into a file */
940 if (silc_file_write_mode(filename, buf->data, buf->len, 0600)) {
941 silc_buffer_free(buf);
945 silc_buffer_free(buf);
949 /* Saves private key into file. */
950 /* XXX The buffer should be encrypted if passphrase is provided. */
952 int silc_pkcs_save_private_key(char *filename, SilcPrivateKey private_key,
953 unsigned char *passphrase,
959 data = silc_pkcs_private_key_encode(private_key, &data_len);
960 return silc_pkcs_save_private_key_internal(filename, data, data_len,
964 /* Saves private key into file. */
965 /* XXX The buffer should be encrypted if passphrase is provided. */
967 int silc_pkcs_save_private_key_data(char *filename, unsigned char *data,
969 unsigned char *passphrase,
972 return silc_pkcs_save_private_key_internal(filename, data, data_len,
976 /* Loads public key from file and allocates new public key. Returns TRUE
977 is loading was successful. */
979 int silc_pkcs_load_public_key(char *filename, SilcPublicKey *public_key,
982 unsigned char *cp, *old, *data, byte;
983 uint32 i, data_len, len;
985 old = data = silc_file_read(filename, &data_len);
989 /* Check start of file and remove header from the data. */
990 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
992 for (i = 0; i < len; i++) {
995 if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
996 memset(old, 0, data_len);
1003 /* Decode public key */
1005 len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1006 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1009 case SILC_PKCS_FILE_BIN:
1011 case SILC_PKCS_FILE_PEM:
1012 data = silc_decode_pem(data, len, &len);
1016 if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
1017 memset(old, 0, data_len);
1023 memset(old, 0, data_len);
1028 /* Load private key from file and allocates new private key. Returns TRUE
1029 if loading was successful. */
1030 /* XXX Should support encrypted private key files */
1032 int silc_pkcs_load_private_key(char *filename, SilcPrivateKey *private_key,
1035 unsigned char *cp, *old, *data, byte;
1036 uint32 i, data_len, len;
1038 old = data = silc_file_read(filename, &data_len);
1042 /* Check start of file and remove header from the data. */
1043 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
1045 for (i = 0; i < len; i++) {
1048 if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
1049 memset(old, 0, data_len);
1056 /* Decode private key */
1058 len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1059 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1062 case SILC_PKCS_FILE_BIN:
1064 case SILC_PKCS_FILE_PEM:
1065 data = silc_decode_pem(data, len, &len);
1069 if (!data || !silc_pkcs_private_key_decode(data, len, private_key)) {
1070 memset(old, 0, data_len);
1076 memset(old, 0, data_len);