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] == '\\') {
453 item = silc_calloc(len + 1, sizeof(char));
454 memcpy(item, cp, len);
456 if (strstr(item, "UN="))
457 ident->username = strdup(item + strcspn(cp, "=") + 1);
458 else if (strstr(item, "HN="))
459 ident->host = strdup(item + strcspn(cp, "=") + 1);
460 else if (strstr(item, "RN="))
461 ident->realname = strdup(item + strcspn(cp, "=") + 1);
462 else if (strstr(item, "E="))
463 ident->email = strdup(item + strcspn(cp, "=") + 1);
464 else if (strstr(item, "O="))
465 ident->org = strdup(item + strcspn(cp, "=") + 1);
466 else if (strstr(item, "C="))
467 ident->country = strdup(item + strcspn(cp, "=") + 1);
482 /* Free's decoded public key identifier context. Call this to free the
483 context returned by the silc_pkcs_decode_identifier. */
485 void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier)
487 silc_free(identifier->username);
488 silc_free(identifier->host);
489 silc_free(identifier->realname);
490 silc_free(identifier->email);
491 silc_free(identifier->org);
492 silc_free(identifier->country);
493 silc_free(identifier);
496 /* Allocates SILC style public key formed from sent arguments. All data
499 SilcPublicKey silc_pkcs_public_key_alloc(char *name, char *identifier,
503 SilcPublicKey public_key;
505 public_key = silc_calloc(1, sizeof(*public_key));
506 public_key->len = 4 + 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
507 public_key->name = strdup(name);
508 public_key->identifier = strdup(identifier);
509 public_key->pk_len = pk_len;
510 public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
511 memcpy(public_key->pk, pk, pk_len);
516 /* Free's public key */
518 void silc_pkcs_public_key_free(SilcPublicKey public_key)
521 silc_free(public_key->name);
522 silc_free(public_key->identifier);
523 silc_free(public_key->pk);
524 silc_free(public_key);
528 /* Allocates SILC private key formed from sent arguments. All data is
531 SilcPrivateKey silc_pkcs_private_key_alloc(char *name, unsigned char *prv,
534 SilcPrivateKey private_key;
536 private_key = silc_calloc(1, sizeof(*private_key));
537 private_key->name = strdup(name);
538 private_key->prv_len = prv_len;
539 private_key->prv = silc_calloc(prv_len, sizeof(*private_key->prv));
540 memcpy(private_key->prv, prv, prv_len);
545 /* Free's private key */
547 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
550 silc_free(private_key->name);
551 silc_free(private_key->prv);
552 silc_free(private_key);
556 /* Encodes SILC style public key from SilcPublicKey. Returns the encoded
560 silc_pkcs_public_key_encode(SilcPublicKey public_key, uint32 *len)
565 buf = silc_buffer_alloc(public_key->len);
566 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
568 silc_buffer_format(buf,
569 SILC_STR_UI_INT(public_key->len),
570 SILC_STR_UI_SHORT(strlen(public_key->name)),
571 SILC_STR_UI32_STRING(public_key->name),
572 SILC_STR_UI_SHORT(strlen(public_key->identifier)),
573 SILC_STR_UI32_STRING(public_key->identifier),
574 SILC_STR_UI_XNSTRING(public_key->pk,
578 *len = public_key->len;
580 ret = silc_calloc(buf->len, sizeof(*ret));
581 memcpy(ret, buf->data, buf->len);
582 silc_buffer_free(buf);
587 /* Encodes SILC style public key. Returns the encoded data. */
590 silc_pkcs_public_key_data_encode(unsigned char *pk, uint32 pk_len,
591 char *pkcs, char *identifier,
598 totlen = 4 + 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
599 buf = silc_buffer_alloc(totlen);
600 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
602 silc_buffer_format(buf,
603 SILC_STR_UI_INT(totlen),
604 SILC_STR_UI_SHORT(strlen(pkcs)),
605 SILC_STR_UI32_STRING(pkcs),
606 SILC_STR_UI_SHORT(strlen(identifier)),
607 SILC_STR_UI32_STRING(identifier),
608 SILC_STR_UI_XNSTRING(pk, pk_len),
613 ret = silc_calloc(buf->len, sizeof(*ret));
614 memcpy(ret, buf->data, buf->len);
615 silc_buffer_free(buf);
620 /* Decodes SILC style public key. Returns TRUE if the decoding was
621 successful. Allocates new public key as well. */
623 int silc_pkcs_public_key_decode(unsigned char *data, uint32 data_len,
624 SilcPublicKey *public_key)
628 uint16 pkcs_len, identifier_len;
629 uint32 totlen, key_len;
630 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
633 buf = silc_buffer_alloc(data_len);
634 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
635 silc_buffer_put(buf, data, data_len);
638 ret = silc_buffer_unformat(buf,
639 SILC_STR_UI_INT(&totlen),
642 silc_buffer_free(buf);
646 if (totlen != data_len) {
647 silc_buffer_free(buf);
651 /* Get algorithm name and identifier */
652 silc_buffer_pull(buf, 4);
654 silc_buffer_unformat(buf,
655 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
656 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
661 if (pkcs_len < 1 || identifier_len < 3 ||
662 pkcs_len + identifier_len > totlen)
665 /* See if we support this algorithm (check only if PKCS are registered) */
666 if (silc_pkcs_list && !silc_pkcs_is_supported(pkcs_name)) {
667 SILC_LOG_DEBUG(("Unknown PKCS %s", pkcs_name));
671 /* Protocol says that at least UN and HN must be provided as identifier,
673 if (!strstr(ident, "UN=") && !strstr(ident, "HN=")) {
674 SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
679 /* Get key data. We assume that rest of the buffer is key data. */
680 silc_buffer_pull(buf, 2 + pkcs_len + 2 + identifier_len);
682 ret = silc_buffer_unformat(buf,
683 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
688 /* Try to set the key. If this fails the key must be malformed. This
689 code assumes that the PKCS routine checks the format of the key.
690 (check only if PKCS are registered) */
691 if (silc_pkcs_list) {
692 silc_pkcs_alloc(pkcs_name, &alg);
693 if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
699 *public_key = silc_calloc(1, sizeof(**public_key));
700 (*public_key)->len = totlen;
701 (*public_key)->name = pkcs_name;
702 (*public_key)->identifier = ident;
703 (*public_key)->pk = key_data;
704 (*public_key)->pk_len = key_len;
707 silc_buffer_free(buf);
712 silc_free(pkcs_name);
717 silc_buffer_free(buf);
721 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
724 silc_pkcs_private_key_encode(SilcPrivateKey private_key, uint32 *len)
730 totlen = 2 + strlen(private_key->name) + private_key->prv_len;
731 buf = silc_buffer_alloc(totlen);
732 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
734 silc_buffer_format(buf,
735 SILC_STR_UI_SHORT(strlen(private_key->name)),
736 SILC_STR_UI32_STRING(private_key->name),
737 SILC_STR_UI_XNSTRING(private_key->prv,
738 private_key->prv_len),
743 ret = silc_calloc(buf->len, sizeof(*ret));
744 memcpy(ret, buf->data, buf->len);
745 silc_buffer_free(buf);
750 /* Encodes SILC private key. Returns the encoded data. */
753 silc_pkcs_private_key_data_encode(unsigned char *prv, uint32 prv_len,
754 char *pkcs, uint32 *len)
760 totlen = 2 + strlen(pkcs) + prv_len;
761 buf = silc_buffer_alloc(totlen);
762 silc_buffer_pull_tail(buf, totlen);
764 silc_buffer_format(buf,
765 SILC_STR_UI_SHORT(strlen(pkcs)),
766 SILC_STR_UI32_STRING(pkcs),
767 SILC_STR_UI_XNSTRING(prv, prv_len),
772 ret = silc_calloc(buf->len, sizeof(*ret));
773 memcpy(ret, buf->data, buf->len);
774 silc_buffer_free(buf);
779 /* Decodes SILC style public key. Returns TRUE if the decoding was
780 successful. Allocates new private key as well. */
782 int silc_pkcs_private_key_decode(unsigned char *data, uint32 data_len,
783 SilcPrivateKey *private_key)
789 unsigned char *pkcs_name = NULL, *key_data = NULL;
792 buf = silc_buffer_alloc(data_len);
793 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
794 silc_buffer_put(buf, data, data_len);
796 /* Get algorithm name and identifier */
798 silc_buffer_unformat(buf,
799 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
804 if (pkcs_len < 1 || pkcs_len > buf->truelen)
807 /* See if we support this algorithm (check only if PKCS are registered). */
808 if (silc_pkcs_list && !silc_pkcs_is_supported(pkcs_name)) {
809 SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
813 /* Get key data. We assume that rest of the buffer is key data. */
814 silc_buffer_pull(buf, 2 + pkcs_len);
816 ret = silc_buffer_unformat(buf,
817 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
822 /* Try to set the key. If this fails the key must be malformed. This
823 code assumes that the PKCS routine checks the format of the key.
824 (check only if PKCS are registered) */
825 if (silc_pkcs_list) {
826 silc_pkcs_alloc(pkcs_name, &alg);
827 if (!alg->pkcs->set_private_key(alg->context, key_data, key_len))
833 *private_key = silc_calloc(1, sizeof(**private_key));
834 (*private_key)->name = pkcs_name;
835 (*private_key)->prv = key_data;
836 (*private_key)->prv_len = key_len;
839 silc_buffer_free(buf);
844 silc_free(pkcs_name);
847 silc_buffer_free(buf);
851 /* Internal routine to save public key */
853 static int silc_pkcs_save_public_key_internal(char *filename,
862 case SILC_PKCS_FILE_BIN:
864 case SILC_PKCS_FILE_PEM:
865 data = silc_encode_pem_file(data, data_len);
866 data_len = strlen(data);
870 len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
871 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
872 buf = silc_buffer_alloc(len);
873 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
875 silc_buffer_format(buf,
876 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
877 SILC_STR_UI_XNSTRING(data, data_len),
878 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
882 if (silc_file_write(filename, buf->data, buf->len)) {
883 silc_buffer_free(buf);
887 silc_buffer_free(buf);
891 /* Saves public key into file */
893 int silc_pkcs_save_public_key(char *filename, SilcPublicKey public_key,
899 data = silc_pkcs_public_key_encode(public_key, &data_len);
900 return silc_pkcs_save_public_key_internal(filename, data, data_len,
904 /* Saves public key into file */
906 int silc_pkcs_save_public_key_data(char *filename, unsigned char *data,
910 return silc_pkcs_save_public_key_internal(filename, data, data_len,
914 /* Internal routine to save private key. */
916 static int silc_pkcs_save_private_key_internal(char *filename,
925 case SILC_PKCS_FILE_BIN:
927 case SILC_PKCS_FILE_PEM:
928 data = silc_encode_pem_file(data, data_len);
929 data_len = strlen(data);
933 len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
934 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
935 buf = silc_buffer_alloc(len);
936 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
938 silc_buffer_format(buf,
939 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
940 SILC_STR_UI_XNSTRING(data, data_len),
941 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
944 /* Save into a file */
945 if (silc_file_write_mode(filename, buf->data, buf->len, 0600)) {
946 silc_buffer_free(buf);
950 silc_buffer_free(buf);
954 /* Saves private key into file. */
955 /* XXX The buffer should be encrypted if passphrase is provided. */
957 int silc_pkcs_save_private_key(char *filename, SilcPrivateKey private_key,
958 unsigned char *passphrase,
964 data = silc_pkcs_private_key_encode(private_key, &data_len);
965 return silc_pkcs_save_private_key_internal(filename, data, data_len,
969 /* Saves private key into file. */
970 /* XXX The buffer should be encrypted if passphrase is provided. */
972 int silc_pkcs_save_private_key_data(char *filename, unsigned char *data,
974 unsigned char *passphrase,
977 return silc_pkcs_save_private_key_internal(filename, data, data_len,
981 /* Loads public key from file and allocates new public key. Returns TRUE
982 is loading was successful. */
984 int silc_pkcs_load_public_key(char *filename, SilcPublicKey *public_key,
987 unsigned char *cp, *old, *data, byte;
988 uint32 i, data_len, len;
990 old = data = silc_file_read(filename, &data_len);
994 /* Check start of file and remove header from the data. */
995 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
997 for (i = 0; i < len; i++) {
1000 if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
1001 memset(old, 0, data_len);
1008 /* Decode public key */
1010 len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
1011 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
1014 case SILC_PKCS_FILE_BIN:
1016 case SILC_PKCS_FILE_PEM:
1017 data = silc_decode_pem(data, len, &len);
1021 if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
1022 memset(old, 0, data_len);
1028 memset(old, 0, data_len);
1033 /* Load private key from file and allocates new private key. Returns TRUE
1034 if loading was successful. */
1035 /* XXX Should support encrypted private key files */
1037 int silc_pkcs_load_private_key(char *filename, SilcPrivateKey *private_key,
1040 unsigned char *cp, *old, *data, byte;
1041 uint32 i, data_len, len;
1043 old = data = silc_file_read(filename, &data_len);
1047 /* Check start of file and remove header from the data. */
1048 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
1050 for (i = 0; i < len; i++) {
1053 if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
1054 memset(old, 0, data_len);
1061 /* Decode private key */
1063 len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
1064 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
1067 case SILC_PKCS_FILE_BIN:
1069 case SILC_PKCS_FILE_PEM:
1070 data = silc_decode_pem(data, len, &len);
1074 if (!data || !silc_pkcs_private_key_decode(data, len, private_key)) {
1075 memset(old, 0, data_len);
1081 memset(old, 0, data_len);