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 pkcs->pkcs->clear_keys(pkcs->context);
157 silc_free(pkcs->context);
162 /* Return TRUE if PKCS algorithm `name' is supported. */
164 int silc_pkcs_is_supported(const unsigned char *name)
166 SilcPKCSObject *entry;
168 if (silc_pkcs_list) {
169 silc_dlist_start(silc_pkcs_list);
170 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
171 if (!strcmp(entry->name, name))
179 /* Returns comma separated list of supported PKCS algorithms */
181 char *silc_pkcs_get_supported(void)
183 SilcPKCSObject *entry;
188 if (silc_pkcs_list) {
189 silc_dlist_start(silc_pkcs_list);
190 while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
191 len += strlen(entry->name);
192 list = silc_realloc(list, len + 1);
194 memcpy(list + (len - strlen(entry->name)),
195 entry->name, strlen(entry->name));
196 memcpy(list + len, ",", 1);
205 /* Returns the length of the key */
207 uint32 silc_pkcs_get_key_len(SilcPKCS pkcs)
209 return pkcs->key_len;
212 /* Returns SILC style public key */
214 unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, uint32 *len)
216 return pkcs->pkcs->get_public_key(pkcs->context, len);
219 /* Returns SILC style private key */
221 unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, uint32 *len)
223 return pkcs->pkcs->get_private_key(pkcs->context, len);
226 /* Sets public key from SilcPublicKey. */
228 uint32 silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
230 pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
232 return pkcs->key_len;
235 /* Sets public key from data. */
237 uint32 silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
240 pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, pk, pk_len);
241 return pkcs->key_len;
244 /* Sets private key from SilcPrivateKey. */
246 int silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
248 return pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
249 private_key->prv_len);
252 /* Sets private key from data. */
254 int silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
257 return pkcs->pkcs->set_private_key(pkcs->context, prv, prv_len);
262 int silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, uint32 src_len,
263 unsigned char *dst, uint32 *dst_len)
265 return pkcs->pkcs->encrypt(pkcs->context, src, src_len, dst, dst_len);
270 int silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, uint32 src_len,
271 unsigned char *dst, uint32 *dst_len)
273 return pkcs->pkcs->decrypt(pkcs->context, src, src_len, dst, dst_len);
276 /* Generates signature */
278 int silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, uint32 src_len,
279 unsigned char *dst, uint32 *dst_len)
281 return pkcs->pkcs->sign(pkcs->context, src, src_len, dst, dst_len);
284 /* Verifies signature */
286 int silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
287 uint32 signature_len, unsigned char *data,
290 return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
294 /* Generates signature with hash. The hash is signed. */
296 int silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
297 unsigned char *src, uint32 src_len,
298 unsigned char *dst, uint32 *dst_len)
300 unsigned char hashr[32];
304 silc_hash_make(hash, src, src_len, hashr);
305 hash_len = hash->hash->hash_len;
307 SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
309 ret = pkcs->pkcs->sign(pkcs->context, hashr, hash_len, dst, dst_len);
310 memset(hashr, 0, sizeof(hashr));
315 /* Verifies signature with hash. The `data' is hashed and verified against
318 int silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
319 unsigned char *signature,
320 uint32 signature_len,
324 unsigned char hashr[32];
328 silc_hash_make(hash, data, data_len, hashr);
329 hash_len = hash->hash->hash_len;
331 SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
333 ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
335 memset(hashr, 0, sizeof(hashr));
340 /* Encodes and returns SILC public key identifier. If some of the
341 arguments is NULL those are not encoded into the identifier string.
342 Protocol says that at least username and host must be provided. */
344 char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
345 char *email, char *org, char *country)
349 uint32 len, tlen = 0;
351 if (!username || !host)
354 len = (username ? strlen(username) : 0) +
355 (host ? strlen(host) : 0) +
356 (realname ? strlen(realname) : 0) +
357 (email ? strlen(email) : 0) +
358 (org ? strlen(org) : 0) +
359 (country ? strlen(country) : 0);
364 len += 3 + 5 + 5 + 4 + 4 + 4;
365 buf = silc_buffer_alloc(len);
366 silc_buffer_pull_tail(buf, len);
369 silc_buffer_format(buf,
370 SILC_STR_UI32_STRING("UN="),
371 SILC_STR_UI32_STRING(username),
373 silc_buffer_pull(buf, 3 + strlen(username));
374 tlen = 3 + strlen(username);
378 silc_buffer_format(buf,
379 SILC_STR_UI32_STRING(", "),
380 SILC_STR_UI32_STRING("HN="),
381 SILC_STR_UI32_STRING(host),
383 silc_buffer_pull(buf, 5 + strlen(host));
384 tlen += 5 + strlen(host);
388 silc_buffer_format(buf,
389 SILC_STR_UI32_STRING(", "),
390 SILC_STR_UI32_STRING("RN="),
391 SILC_STR_UI32_STRING(realname),
393 silc_buffer_pull(buf, 5 + strlen(realname));
394 tlen += 5 + strlen(realname);
398 silc_buffer_format(buf,
399 SILC_STR_UI32_STRING(", "),
400 SILC_STR_UI32_STRING("E="),
401 SILC_STR_UI32_STRING(email),
403 silc_buffer_pull(buf, 4 + strlen(email));
404 tlen += 4 + strlen(email);
408 silc_buffer_format(buf,
409 SILC_STR_UI32_STRING(", "),
410 SILC_STR_UI32_STRING("O="),
411 SILC_STR_UI32_STRING(org),
413 silc_buffer_pull(buf, 4 + strlen(org));
414 tlen += 4 + strlen(org);
418 silc_buffer_format(buf,
419 SILC_STR_UI32_STRING(", "),
420 SILC_STR_UI32_STRING("C="),
421 SILC_STR_UI32_STRING(country),
423 silc_buffer_pull(buf, 4 + strlen(country));
424 tlen += 4 + strlen(country);
427 silc_buffer_push(buf, buf->data - buf->head);
428 identifier = silc_calloc(tlen + 1, sizeof(*identifier));
429 memcpy(identifier, buf->data, tlen);
430 silc_buffer_free(buf);
435 /* Decodes the provided `identifier' and returns allocated context for
438 SilcPublicKeyIdentifier silc_pkcs_decode_identifier(char *identifier)
440 SilcPublicKeyIdentifier ident;
444 ident = silc_calloc(1, sizeof(*ident));
448 len = strcspn(cp, ",");
449 if (len - 1 >= 0 && cp[len - 1] == '\\') {
452 len = strcspn(cp, ",") + len;
453 if (len - 1 >= 0 && cp[len - 1] != '\\')
458 item = silc_calloc(len + 1, sizeof(char));
459 memcpy(item, cp, len);
461 if (strstr(item, "UN="))
462 ident->username = strdup(item + strcspn(cp, "=") + 1);
463 else if (strstr(item, "HN="))
464 ident->host = strdup(item + strcspn(cp, "=") + 1);
465 else if (strstr(item, "RN="))
466 ident->realname = strdup(item + strcspn(cp, "=") + 1);
467 else if (strstr(item, "E="))
468 ident->email = strdup(item + strcspn(cp, "=") + 1);
469 else if (strstr(item, "O="))
470 ident->org = strdup(item + strcspn(cp, "=") + 1);
471 else if (strstr(item, "C="))
472 ident->country = strdup(item + strcspn(cp, "=") + 1);
487 /* Free's decoded public key identifier context. Call this to free the
488 context returned by the silc_pkcs_decode_identifier. */
490 void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier)
492 silc_free(identifier->username);
493 silc_free(identifier->host);
494 silc_free(identifier->realname);
495 silc_free(identifier->email);
496 silc_free(identifier->org);
497 silc_free(identifier->country);
498 silc_free(identifier);
501 /* Allocates SILC style public key formed from sent arguments. All data
504 SilcPublicKey silc_pkcs_public_key_alloc(char *name, char *identifier,
508 SilcPublicKey public_key;
510 public_key = silc_calloc(1, sizeof(*public_key));
511 public_key->len = 4 + 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
512 public_key->name = strdup(name);
513 public_key->identifier = strdup(identifier);
514 public_key->pk_len = pk_len;
515 public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
516 memcpy(public_key->pk, pk, pk_len);
521 /* Free's public key */
523 void silc_pkcs_public_key_free(SilcPublicKey public_key)
526 silc_free(public_key->name);
527 silc_free(public_key->identifier);
528 silc_free(public_key->pk);
529 silc_free(public_key);
533 /* Allocates SILC private key formed from sent arguments. All data is
536 SilcPrivateKey silc_pkcs_private_key_alloc(char *name, unsigned char *prv,
539 SilcPrivateKey private_key;
541 private_key = silc_calloc(1, sizeof(*private_key));
542 private_key->name = strdup(name);
543 private_key->prv_len = prv_len;
544 private_key->prv = silc_calloc(prv_len, sizeof(*private_key->prv));
545 memcpy(private_key->prv, prv, prv_len);
550 /* Free's private key */
552 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
555 silc_free(private_key->name);
556 silc_free(private_key->prv);
557 silc_free(private_key);
561 /* Encodes SILC style public key from SilcPublicKey. Returns the encoded
565 silc_pkcs_public_key_encode(SilcPublicKey public_key, uint32 *len)
570 buf = silc_buffer_alloc(public_key->len);
571 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
573 silc_buffer_format(buf,
574 SILC_STR_UI_INT(public_key->len),
575 SILC_STR_UI_SHORT(strlen(public_key->name)),
576 SILC_STR_UI32_STRING(public_key->name),
577 SILC_STR_UI_SHORT(strlen(public_key->identifier)),
578 SILC_STR_UI32_STRING(public_key->identifier),
579 SILC_STR_UI_XNSTRING(public_key->pk,
583 *len = public_key->len;
585 ret = silc_calloc(buf->len, sizeof(*ret));
586 memcpy(ret, buf->data, buf->len);
587 silc_buffer_free(buf);
592 /* Encodes SILC style public key. Returns the encoded data. */
595 silc_pkcs_public_key_data_encode(unsigned char *pk, uint32 pk_len,
596 char *pkcs, char *identifier,
603 totlen = 4 + 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
604 buf = silc_buffer_alloc(totlen);
605 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
607 silc_buffer_format(buf,
608 SILC_STR_UI_INT(totlen),
609 SILC_STR_UI_SHORT(strlen(pkcs)),
610 SILC_STR_UI32_STRING(pkcs),
611 SILC_STR_UI_SHORT(strlen(identifier)),
612 SILC_STR_UI32_STRING(identifier),
613 SILC_STR_UI_XNSTRING(pk, pk_len),
618 ret = silc_calloc(buf->len, sizeof(*ret));
619 memcpy(ret, buf->data, buf->len);
620 silc_buffer_free(buf);
625 /* Decodes SILC style public key. Returns TRUE if the decoding was
626 successful. Allocates new public key as well. */
628 int silc_pkcs_public_key_decode(unsigned char *data, uint32 data_len,
629 SilcPublicKey *public_key)
633 uint16 pkcs_len, identifier_len;
634 uint32 totlen, key_len;
635 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
638 buf = silc_buffer_alloc(data_len);
639 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
640 silc_buffer_put(buf, data, data_len);
643 ret = silc_buffer_unformat(buf,
644 SILC_STR_UI_INT(&totlen),
647 silc_buffer_free(buf);
651 if (totlen != data_len) {
652 silc_buffer_free(buf);
656 /* Get algorithm name and identifier */
657 silc_buffer_pull(buf, 4);
659 silc_buffer_unformat(buf,
660 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
661 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
666 if (pkcs_len < 1 || identifier_len < 3 ||
667 pkcs_len + identifier_len > totlen)
670 /* See if we support this algorithm (check only if PKCS are registered) */
671 if (silc_pkcs_list && !silc_pkcs_is_supported(pkcs_name)) {
672 SILC_LOG_DEBUG(("Unknown PKCS %s", pkcs_name));
676 /* Protocol says that at least UN and HN must be provided as identifier,
678 if (!strstr(ident, "UN=") && !strstr(ident, "HN=")) {
679 SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
684 /* Get key data. We assume that rest of the buffer is key data. */
685 silc_buffer_pull(buf, 2 + pkcs_len + 2 + identifier_len);
687 ret = silc_buffer_unformat(buf,
688 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
693 /* Try to set the key. If this fails the key must be malformed. This
694 code assumes that the PKCS routine checks the format of the key.
695 (check only if PKCS are registered) */
696 if (silc_pkcs_list) {
697 silc_pkcs_alloc(pkcs_name, &alg);
698 if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
704 *public_key = silc_calloc(1, sizeof(**public_key));
705 (*public_key)->len = totlen;
706 (*public_key)->name = pkcs_name;
707 (*public_key)->identifier = ident;
708 (*public_key)->pk = key_data;
709 (*public_key)->pk_len = key_len;
712 silc_buffer_free(buf);
717 silc_free(pkcs_name);
722 silc_buffer_free(buf);
726 /* Compares two public keys and returns TRUE if they are same key, and
727 FALSE if they are not same. */
729 bool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
734 if (key1->len == key2->len &&
735 key1->name && key2->name && key1->identifier && key2->identifier &&
736 !strcmp(key1->name, key2->name) &&
737 !strcmp(key1->identifier, key2->identifier) &&
738 !memcmp(key1->pk, key2->pk, key1->pk_len) &&
739 key1->pk_len == key2->pk_len)
745 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
748 silc_pkcs_private_key_encode(SilcPrivateKey private_key, uint32 *len)
754 totlen = 2 + strlen(private_key->name) + private_key->prv_len;
755 buf = silc_buffer_alloc(totlen);
756 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
758 silc_buffer_format(buf,
759 SILC_STR_UI_SHORT(strlen(private_key->name)),
760 SILC_STR_UI32_STRING(private_key->name),
761 SILC_STR_UI_XNSTRING(private_key->prv,
762 private_key->prv_len),
767 ret = silc_calloc(buf->len, sizeof(*ret));
768 memcpy(ret, buf->data, buf->len);
769 silc_buffer_free(buf);
774 /* Encodes SILC private key. Returns the encoded data. */
777 silc_pkcs_private_key_data_encode(unsigned char *prv, uint32 prv_len,
778 char *pkcs, uint32 *len)
784 totlen = 2 + strlen(pkcs) + prv_len;
785 buf = silc_buffer_alloc(totlen);
786 silc_buffer_pull_tail(buf, totlen);
788 silc_buffer_format(buf,
789 SILC_STR_UI_SHORT(strlen(pkcs)),
790 SILC_STR_UI32_STRING(pkcs),
791 SILC_STR_UI_XNSTRING(prv, prv_len),
796 ret = silc_calloc(buf->len, sizeof(*ret));
797 memcpy(ret, buf->data, buf->len);
798 silc_buffer_free(buf);
803 /* Decodes SILC style public key. Returns TRUE if the decoding was
804 successful. Allocates new private key as well. */
806 int silc_pkcs_private_key_decode(unsigned char *data, uint32 data_len,
807 SilcPrivateKey *private_key)
813 unsigned char *pkcs_name = NULL, *key_data = NULL;
816 buf = silc_buffer_alloc(data_len);
817 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
818 silc_buffer_put(buf, data, data_len);
820 /* Get algorithm name and identifier */
822 silc_buffer_unformat(buf,
823 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
828 if (pkcs_len < 1 || pkcs_len > buf->truelen)
831 /* See if we support this algorithm (check only if PKCS are registered). */
832 if (silc_pkcs_list && !silc_pkcs_is_supported(pkcs_name)) {
833 SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
837 /* Get key data. We assume that rest of the buffer is key data. */
838 silc_buffer_pull(buf, 2 + pkcs_len);
840 ret = silc_buffer_unformat(buf,
841 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
846 /* Try to set the key. If this fails the key must be malformed. This
847 code assumes that the PKCS routine checks the format of the key.
848 (check only if PKCS are registered) */
849 if (silc_pkcs_list) {
850 silc_pkcs_alloc(pkcs_name, &alg);
851 if (!alg->pkcs->set_private_key(alg->context, key_data, key_len))
857 *private_key = silc_calloc(1, sizeof(**private_key));
858 (*private_key)->name = pkcs_name;
859 (*private_key)->prv = key_data;
860 (*private_key)->prv_len = key_len;
863 silc_buffer_free(buf);
868 silc_free(pkcs_name);
871 silc_buffer_free(buf);
875 /* Internal routine to save public key */
877 static int silc_pkcs_save_public_key_internal(char *filename,
886 case SILC_PKCS_FILE_BIN:
888 case SILC_PKCS_FILE_PEM:
889 data = silc_encode_pem_file(data, data_len);
890 data_len = strlen(data);
894 len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
895 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
896 buf = silc_buffer_alloc(len);
897 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
899 silc_buffer_format(buf,
900 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
901 SILC_STR_UI_XNSTRING(data, data_len),
902 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
906 if (silc_file_writefile(filename, buf->data, buf->len)) {
907 silc_buffer_free(buf);
911 silc_buffer_free(buf);
915 /* Saves public key into file */
917 int silc_pkcs_save_public_key(char *filename, SilcPublicKey public_key,
923 data = silc_pkcs_public_key_encode(public_key, &data_len);
924 return silc_pkcs_save_public_key_internal(filename, data, data_len,
928 /* Saves public key into file */
930 int silc_pkcs_save_public_key_data(char *filename, unsigned char *data,
934 return silc_pkcs_save_public_key_internal(filename, data, data_len,
938 /* Internal routine to save private key. */
940 static int silc_pkcs_save_private_key_internal(char *filename,
949 case SILC_PKCS_FILE_BIN:
951 case SILC_PKCS_FILE_PEM:
952 data = silc_encode_pem_file(data, data_len);
953 data_len = strlen(data);
957 len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
958 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
959 buf = silc_buffer_alloc(len);
960 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
962 silc_buffer_format(buf,
963 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
964 SILC_STR_UI_XNSTRING(data, data_len),
965 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
968 /* Save into a file */
969 if (silc_file_writefile_mode(filename, buf->data, buf->len, 0600)) {
970 silc_buffer_free(buf);
974 silc_buffer_free(buf);
978 /* Saves private key into file. */
979 /* XXX The buffer should be encrypted if passphrase is provided. */
981 int silc_pkcs_save_private_key(char *filename, SilcPrivateKey private_key,
982 unsigned char *passphrase,
988 data = silc_pkcs_private_key_encode(private_key, &data_len);
989 return silc_pkcs_save_private_key_internal(filename, data, data_len,
993 /* Saves private key into file. */
994 /* XXX The buffer should be encrypted if passphrase is provided. */
996 int silc_pkcs_save_private_key_data(char *filename, unsigned char *data,
998 unsigned char *passphrase,
1001 return silc_pkcs_save_private_key_internal(filename, data, data_len,
1005 /* Loads public key from file and allocates new public key. Returns TRUE
1006 is loading was successful. */
1008 int silc_pkcs_load_public_key(char *filename, SilcPublicKey *public_key,
1011 unsigned char *cp, *old, *data, byte;
1012 uint32 i, data_len, len;
1014 old = data = silc_file_readfile(filename, &data_len);
1018 /* Check start of file and remove header from the data. */
1019 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
1021 for (i = 0; i < len; i++) {
1024 if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
1025 memset(old, 0, data_len);
1032 /* Decode public key */
1034 len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1035 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1038 case SILC_PKCS_FILE_BIN:
1040 case SILC_PKCS_FILE_PEM:
1041 data = silc_decode_pem(data, len, &len);
1045 if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
1046 memset(old, 0, data_len);
1052 memset(old, 0, data_len);
1057 /* Load private key from file and allocates new private key. Returns TRUE
1058 if loading was successful. */
1059 /* XXX Should support encrypted private key files */
1061 int silc_pkcs_load_private_key(char *filename, SilcPrivateKey *private_key,
1064 unsigned char *cp, *old, *data, byte;
1065 uint32 i, data_len, len;
1067 old = data = silc_file_readfile(filename, &data_len);
1071 /* Check start of file and remove header from the data. */
1072 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
1074 for (i = 0; i < len; i++) {
1077 if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
1078 memset(old, 0, data_len);
1085 /* Decode private key */
1087 len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1088 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1091 case SILC_PKCS_FILE_BIN:
1093 case SILC_PKCS_FILE_PEM:
1094 data = silc_decode_pem(data, len, &len);
1098 if (!data || !silc_pkcs_private_key_decode(data, len, private_key)) {
1099 memset(old, 0, data_len);
1105 memset(old, 0, data_len);