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);
203 /* Returns the length of the key */
205 uint32 silc_pkcs_get_key_len(SilcPKCS self)
207 return self->key_len;
210 /* Returns SILC style public key */
212 unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, uint32 *len)
214 return pkcs->pkcs->get_public_key(pkcs->context, len);
217 /* Returns SILC style private key */
219 unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, uint32 *len)
221 return pkcs->pkcs->get_private_key(pkcs->context, len);
224 /* Sets public key from SilcPublicKey. */
226 uint32 silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
228 pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
230 return pkcs->key_len;
233 /* Sets public key from data. */
235 uint32 silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
238 pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, pk, pk_len);
239 return pkcs->key_len;
242 /* Sets private key from SilcPrivateKey. */
244 int silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
246 return pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
247 private_key->prv_len);
250 /* Sets private key from data. */
252 int silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
255 return pkcs->pkcs->set_private_key(pkcs->context, prv, prv_len);
260 int silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, uint32 src_len,
261 unsigned char *dst, uint32 *dst_len)
263 return pkcs->pkcs->encrypt(pkcs->context, src, src_len, dst, dst_len);
268 int silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, uint32 src_len,
269 unsigned char *dst, uint32 *dst_len)
271 return pkcs->pkcs->decrypt(pkcs->context, src, src_len, dst, dst_len);
274 /* Generates signature */
276 int silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, uint32 src_len,
277 unsigned char *dst, uint32 *dst_len)
279 return pkcs->pkcs->sign(pkcs->context, src, src_len, dst, dst_len);
282 /* Verifies signature */
284 int silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
285 uint32 signature_len, unsigned char *data,
288 return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
292 /* Generates signature with hash. The hash is signed. */
294 int silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
295 unsigned char *src, uint32 src_len,
296 unsigned char *dst, uint32 *dst_len)
298 unsigned char hashr[32];
302 silc_hash_make(hash, src, src_len, hashr);
303 hash_len = hash->hash->hash_len;
305 SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
307 ret = pkcs->pkcs->sign(pkcs->context, hashr, hash_len, dst, dst_len);
308 memset(hashr, 0, sizeof(hashr));
313 /* Verifies signature with hash. The `data' is hashed and verified against
316 int silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
317 unsigned char *signature,
318 uint32 signature_len,
322 unsigned char hashr[32];
326 silc_hash_make(hash, data, data_len, hashr);
327 hash_len = hash->hash->hash_len;
329 SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
331 ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
333 memset(hashr, 0, sizeof(hashr));
338 /* Encodes and returns SILC public key identifier. If some of the
339 arguments is NULL those are not encoded into the identifier string.
340 Protocol says that at least username and host must be provided. */
342 char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
343 char *email, char *org, char *country)
347 uint32 len, tlen = 0;
349 if (!username || !host)
352 len = (username ? strlen(username) : 0) +
353 (host ? strlen(host) : 0) +
354 (realname ? strlen(realname) : 0) +
355 (email ? strlen(email) : 0) +
356 (org ? strlen(org) : 0) +
357 (country ? strlen(country) : 0);
362 len += 3 + 5 + 5 + 4 + 4 + 4;
363 buf = silc_buffer_alloc(len);
364 silc_buffer_pull_tail(buf, len);
367 silc_buffer_format(buf,
368 SILC_STR_UI32_STRING("UN="),
369 SILC_STR_UI32_STRING(username),
371 silc_buffer_pull(buf, 3 + strlen(username));
372 tlen = 3 + strlen(username);
376 silc_buffer_format(buf,
377 SILC_STR_UI32_STRING(", "),
378 SILC_STR_UI32_STRING("HN="),
379 SILC_STR_UI32_STRING(host),
381 silc_buffer_pull(buf, 5 + strlen(host));
382 tlen += 5 + strlen(host);
386 silc_buffer_format(buf,
387 SILC_STR_UI32_STRING(", "),
388 SILC_STR_UI32_STRING("RN="),
389 SILC_STR_UI32_STRING(realname),
391 silc_buffer_pull(buf, 5 + strlen(realname));
392 tlen += 5 + strlen(realname);
396 silc_buffer_format(buf,
397 SILC_STR_UI32_STRING(", "),
398 SILC_STR_UI32_STRING("E="),
399 SILC_STR_UI32_STRING(email),
401 silc_buffer_pull(buf, 4 + strlen(email));
402 tlen += 4 + strlen(email);
406 silc_buffer_format(buf,
407 SILC_STR_UI32_STRING(", "),
408 SILC_STR_UI32_STRING("O="),
409 SILC_STR_UI32_STRING(org),
411 silc_buffer_pull(buf, 4 + strlen(org));
412 tlen += 4 + strlen(org);
416 silc_buffer_format(buf,
417 SILC_STR_UI32_STRING(", "),
418 SILC_STR_UI32_STRING("C="),
419 SILC_STR_UI32_STRING(country),
421 silc_buffer_pull(buf, 4 + strlen(country));
422 tlen += 4 + strlen(country);
425 silc_buffer_push(buf, buf->data - buf->head);
426 identifier = silc_calloc(tlen + 1, sizeof(*identifier));
427 memcpy(identifier, buf->data, tlen);
428 silc_buffer_free(buf);
433 /* Decodes the provided `identifier' and returns allocated context for
436 SilcPublicKeyIdentifier silc_pkcs_decode_identifier(char *identifier)
438 SilcPublicKeyIdentifier ident;
442 ident = silc_calloc(1, sizeof(*ident));
446 len = strcspn(cp, ",");
447 if (len - 1 >= 0 && cp[len - 1] == '\\') {
450 len = strcspn(cp, ",") + len;
451 if (len - 1 >= 0 && cp[len - 1] != '\\')
456 item = silc_calloc(len + 1, sizeof(char));
457 memcpy(item, cp, len);
459 if (strstr(item, "UN="))
460 ident->username = strdup(item + strcspn(cp, "=") + 1);
461 else if (strstr(item, "HN="))
462 ident->host = strdup(item + strcspn(cp, "=") + 1);
463 else if (strstr(item, "RN="))
464 ident->realname = strdup(item + strcspn(cp, "=") + 1);
465 else if (strstr(item, "E="))
466 ident->email = strdup(item + strcspn(cp, "=") + 1);
467 else if (strstr(item, "O="))
468 ident->org = strdup(item + strcspn(cp, "=") + 1);
469 else if (strstr(item, "C="))
470 ident->country = strdup(item + strcspn(cp, "=") + 1);
485 /* Free's decoded public key identifier context. Call this to free the
486 context returned by the silc_pkcs_decode_identifier. */
488 void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier)
490 silc_free(identifier->username);
491 silc_free(identifier->host);
492 silc_free(identifier->realname);
493 silc_free(identifier->email);
494 silc_free(identifier->org);
495 silc_free(identifier->country);
496 silc_free(identifier);
499 /* Allocates SILC style public key formed from sent arguments. All data
502 SilcPublicKey silc_pkcs_public_key_alloc(char *name, char *identifier,
506 SilcPublicKey public_key;
508 public_key = silc_calloc(1, sizeof(*public_key));
509 public_key->len = 4 + 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
510 public_key->name = strdup(name);
511 public_key->identifier = strdup(identifier);
512 public_key->pk_len = pk_len;
513 public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
514 memcpy(public_key->pk, pk, pk_len);
519 /* Free's public key */
521 void silc_pkcs_public_key_free(SilcPublicKey public_key)
524 silc_free(public_key->name);
525 silc_free(public_key->identifier);
526 silc_free(public_key->pk);
527 silc_free(public_key);
531 /* Allocates SILC private key formed from sent arguments. All data is
534 SilcPrivateKey silc_pkcs_private_key_alloc(char *name, unsigned char *prv,
537 SilcPrivateKey private_key;
539 private_key = silc_calloc(1, sizeof(*private_key));
540 private_key->name = strdup(name);
541 private_key->prv_len = prv_len;
542 private_key->prv = silc_calloc(prv_len, sizeof(*private_key->prv));
543 memcpy(private_key->prv, prv, prv_len);
548 /* Free's private key */
550 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
553 silc_free(private_key->name);
554 silc_free(private_key->prv);
555 silc_free(private_key);
559 /* Encodes SILC style public key from SilcPublicKey. Returns the encoded
563 silc_pkcs_public_key_encode(SilcPublicKey public_key, uint32 *len)
568 buf = silc_buffer_alloc(public_key->len);
569 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
571 silc_buffer_format(buf,
572 SILC_STR_UI_INT(public_key->len),
573 SILC_STR_UI_SHORT(strlen(public_key->name)),
574 SILC_STR_UI32_STRING(public_key->name),
575 SILC_STR_UI_SHORT(strlen(public_key->identifier)),
576 SILC_STR_UI32_STRING(public_key->identifier),
577 SILC_STR_UI_XNSTRING(public_key->pk,
581 *len = public_key->len;
583 ret = silc_calloc(buf->len, sizeof(*ret));
584 memcpy(ret, buf->data, buf->len);
585 silc_buffer_free(buf);
590 /* Encodes SILC style public key. Returns the encoded data. */
593 silc_pkcs_public_key_data_encode(unsigned char *pk, uint32 pk_len,
594 char *pkcs, char *identifier,
601 totlen = 4 + 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
602 buf = silc_buffer_alloc(totlen);
603 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
605 silc_buffer_format(buf,
606 SILC_STR_UI_INT(totlen),
607 SILC_STR_UI_SHORT(strlen(pkcs)),
608 SILC_STR_UI32_STRING(pkcs),
609 SILC_STR_UI_SHORT(strlen(identifier)),
610 SILC_STR_UI32_STRING(identifier),
611 SILC_STR_UI_XNSTRING(pk, pk_len),
616 ret = silc_calloc(buf->len, sizeof(*ret));
617 memcpy(ret, buf->data, buf->len);
618 silc_buffer_free(buf);
623 /* Decodes SILC style public key. Returns TRUE if the decoding was
624 successful. Allocates new public key as well. */
626 int silc_pkcs_public_key_decode(unsigned char *data, uint32 data_len,
627 SilcPublicKey *public_key)
631 uint16 pkcs_len, identifier_len;
632 uint32 totlen, key_len;
633 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
636 buf = silc_buffer_alloc(data_len);
637 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
638 silc_buffer_put(buf, data, data_len);
641 ret = silc_buffer_unformat(buf,
642 SILC_STR_UI_INT(&totlen),
645 silc_buffer_free(buf);
649 if (totlen != data_len) {
650 silc_buffer_free(buf);
654 /* Get algorithm name and identifier */
655 silc_buffer_pull(buf, 4);
657 silc_buffer_unformat(buf,
658 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
659 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
664 if (pkcs_len < 1 || identifier_len < 3 ||
665 pkcs_len + identifier_len > totlen)
668 /* See if we support this algorithm (check only if PKCS are registered) */
669 if (silc_pkcs_list && !silc_pkcs_is_supported(pkcs_name)) {
670 SILC_LOG_DEBUG(("Unknown PKCS %s", pkcs_name));
674 /* Protocol says that at least UN and HN must be provided as identifier,
676 if (!strstr(ident, "UN=") && !strstr(ident, "HN=")) {
677 SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
682 /* Get key data. We assume that rest of the buffer is key data. */
683 silc_buffer_pull(buf, 2 + pkcs_len + 2 + identifier_len);
685 ret = silc_buffer_unformat(buf,
686 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
691 /* Try to set the key. If this fails the key must be malformed. This
692 code assumes that the PKCS routine checks the format of the key.
693 (check only if PKCS are registered) */
694 if (silc_pkcs_list) {
695 silc_pkcs_alloc(pkcs_name, &alg);
696 if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
702 *public_key = silc_calloc(1, sizeof(**public_key));
703 (*public_key)->len = totlen;
704 (*public_key)->name = pkcs_name;
705 (*public_key)->identifier = ident;
706 (*public_key)->pk = key_data;
707 (*public_key)->pk_len = key_len;
710 silc_buffer_free(buf);
715 silc_free(pkcs_name);
720 silc_buffer_free(buf);
724 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
727 silc_pkcs_private_key_encode(SilcPrivateKey private_key, uint32 *len)
733 totlen = 2 + strlen(private_key->name) + private_key->prv_len;
734 buf = silc_buffer_alloc(totlen);
735 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
737 silc_buffer_format(buf,
738 SILC_STR_UI_SHORT(strlen(private_key->name)),
739 SILC_STR_UI32_STRING(private_key->name),
740 SILC_STR_UI_XNSTRING(private_key->prv,
741 private_key->prv_len),
746 ret = silc_calloc(buf->len, sizeof(*ret));
747 memcpy(ret, buf->data, buf->len);
748 silc_buffer_free(buf);
753 /* Encodes SILC private key. Returns the encoded data. */
756 silc_pkcs_private_key_data_encode(unsigned char *prv, uint32 prv_len,
757 char *pkcs, uint32 *len)
763 totlen = 2 + strlen(pkcs) + prv_len;
764 buf = silc_buffer_alloc(totlen);
765 silc_buffer_pull_tail(buf, totlen);
767 silc_buffer_format(buf,
768 SILC_STR_UI_SHORT(strlen(pkcs)),
769 SILC_STR_UI32_STRING(pkcs),
770 SILC_STR_UI_XNSTRING(prv, prv_len),
775 ret = silc_calloc(buf->len, sizeof(*ret));
776 memcpy(ret, buf->data, buf->len);
777 silc_buffer_free(buf);
782 /* Decodes SILC style public key. Returns TRUE if the decoding was
783 successful. Allocates new private key as well. */
785 int silc_pkcs_private_key_decode(unsigned char *data, uint32 data_len,
786 SilcPrivateKey *private_key)
792 unsigned char *pkcs_name = NULL, *key_data = NULL;
795 buf = silc_buffer_alloc(data_len);
796 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
797 silc_buffer_put(buf, data, data_len);
799 /* Get algorithm name and identifier */
801 silc_buffer_unformat(buf,
802 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
807 if (pkcs_len < 1 || pkcs_len > buf->truelen)
810 /* See if we support this algorithm (check only if PKCS are registered). */
811 if (silc_pkcs_list && !silc_pkcs_is_supported(pkcs_name)) {
812 SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
816 /* Get key data. We assume that rest of the buffer is key data. */
817 silc_buffer_pull(buf, 2 + pkcs_len);
819 ret = silc_buffer_unformat(buf,
820 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
825 /* Try to set the key. If this fails the key must be malformed. This
826 code assumes that the PKCS routine checks the format of the key.
827 (check only if PKCS are registered) */
828 if (silc_pkcs_list) {
829 silc_pkcs_alloc(pkcs_name, &alg);
830 if (!alg->pkcs->set_private_key(alg->context, key_data, key_len))
836 *private_key = silc_calloc(1, sizeof(**private_key));
837 (*private_key)->name = pkcs_name;
838 (*private_key)->prv = key_data;
839 (*private_key)->prv_len = key_len;
842 silc_buffer_free(buf);
847 silc_free(pkcs_name);
850 silc_buffer_free(buf);
854 /* Internal routine to save public key */
856 static int silc_pkcs_save_public_key_internal(char *filename,
865 case SILC_PKCS_FILE_BIN:
867 case SILC_PKCS_FILE_PEM:
868 data = silc_encode_pem_file(data, data_len);
869 data_len = strlen(data);
873 len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
874 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
875 buf = silc_buffer_alloc(len);
876 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
878 silc_buffer_format(buf,
879 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
880 SILC_STR_UI_XNSTRING(data, data_len),
881 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
885 if (silc_file_writefile(filename, buf->data, buf->len)) {
886 silc_buffer_free(buf);
890 silc_buffer_free(buf);
894 /* Saves public key into file */
896 int silc_pkcs_save_public_key(char *filename, SilcPublicKey public_key,
902 data = silc_pkcs_public_key_encode(public_key, &data_len);
903 return silc_pkcs_save_public_key_internal(filename, data, data_len,
907 /* Saves public key into file */
909 int silc_pkcs_save_public_key_data(char *filename, unsigned char *data,
913 return silc_pkcs_save_public_key_internal(filename, data, data_len,
917 /* Internal routine to save private key. */
919 static int silc_pkcs_save_private_key_internal(char *filename,
928 case SILC_PKCS_FILE_BIN:
930 case SILC_PKCS_FILE_PEM:
931 data = silc_encode_pem_file(data, data_len);
932 data_len = strlen(data);
936 len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
937 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
938 buf = silc_buffer_alloc(len);
939 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
941 silc_buffer_format(buf,
942 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
943 SILC_STR_UI_XNSTRING(data, data_len),
944 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
947 /* Save into a file */
948 if (silc_file_writefile_mode(filename, buf->data, buf->len, 0600)) {
949 silc_buffer_free(buf);
953 silc_buffer_free(buf);
957 /* Saves private key into file. */
958 /* XXX The buffer should be encrypted if passphrase is provided. */
960 int silc_pkcs_save_private_key(char *filename, SilcPrivateKey private_key,
961 unsigned char *passphrase,
967 data = silc_pkcs_private_key_encode(private_key, &data_len);
968 return silc_pkcs_save_private_key_internal(filename, data, data_len,
972 /* Saves private key into file. */
973 /* XXX The buffer should be encrypted if passphrase is provided. */
975 int silc_pkcs_save_private_key_data(char *filename, unsigned char *data,
977 unsigned char *passphrase,
980 return silc_pkcs_save_private_key_internal(filename, data, data_len,
984 /* Loads public key from file and allocates new public key. Returns TRUE
985 is loading was successful. */
987 int silc_pkcs_load_public_key(char *filename, SilcPublicKey *public_key,
990 unsigned char *cp, *old, *data, byte;
991 uint32 i, data_len, len;
993 old = data = silc_file_readfile(filename, &data_len);
997 /* Check start of file and remove header from the data. */
998 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
1000 for (i = 0; i < len; i++) {
1003 if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
1004 memset(old, 0, data_len);
1011 /* Decode public key */
1013 len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1014 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1017 case SILC_PKCS_FILE_BIN:
1019 case SILC_PKCS_FILE_PEM:
1020 data = silc_decode_pem(data, len, &len);
1024 if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
1025 memset(old, 0, data_len);
1031 memset(old, 0, data_len);
1036 /* Load private key from file and allocates new private key. Returns TRUE
1037 if loading was successful. */
1038 /* XXX Should support encrypted private key files */
1040 int silc_pkcs_load_private_key(char *filename, SilcPrivateKey *private_key,
1043 unsigned char *cp, *old, *data, byte;
1044 uint32 i, data_len, len;
1046 old = data = silc_file_readfile(filename, &data_len);
1050 /* Check start of file and remove header from the data. */
1051 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
1053 for (i = 0; i < len; i++) {
1056 if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
1057 memset(old, 0, data_len);
1064 /* Decode private key */
1066 len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1067 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1070 case SILC_PKCS_FILE_BIN:
1072 case SILC_PKCS_FILE_PEM:
1073 data = silc_decode_pem(data, len, &len);
1077 if (!data || !silc_pkcs_private_key_decode(data, len, private_key)) {
1078 memset(old, 0, data_len);
1084 memset(old, 0, data_len);