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 /* List of all PKCS's in SILC. PKCS's don't support SIM's thus
28 only static declarations are possible. XXX: I hope this to change
30 SilcPKCSObject silc_pkcs_list[] =
32 /* RSA with PKCS #1 (Uses directly routines from Raw RSA operations) */
33 { "rsa", &silc_rsa_data_context,
34 silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
35 silc_rsa_get_private_key, silc_rsa_set_public_key,
36 silc_rsa_set_private_key, silc_rsa_context_len,
37 silc_rsa_data_context_len, silc_rsa_set_arg,
38 silc_pkcs1_encrypt, silc_pkcs1_decrypt,
39 silc_pkcs1_sign, silc_pkcs1_verify },
41 /* Raw RSA operations */
42 { "rsa-raw", &silc_rsa_data_context,
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_data_context_len, silc_rsa_set_arg,
47 silc_rsa_encrypt, silc_rsa_decrypt,
48 silc_rsa_sign, silc_rsa_verify },
50 { NULL, NULL, NULL, NULL, NULL,
51 NULL, NULL, NULL, NULL, NULL, NULL }
54 /* Allocates a new SilcPKCS object. The new allocated object is returned
55 to the 'new_pkcs' argument. This function also initializes the data
56 context structure. Function returns 1 on success and 0 on error.
59 int silc_pkcs_alloc(const unsigned char *name, SilcPKCS *new_pkcs)
63 SILC_LOG_DEBUG(("Allocating new PKCS object"));
65 for (i = 0; silc_pkcs_list[i].name; i++) {
66 if (!strcmp(silc_pkcs_list[i].name, name))
70 if (silc_pkcs_list[i].name == NULL)
73 *new_pkcs = silc_calloc(1, sizeof(**new_pkcs));
75 /* Set the pointers */
76 (*new_pkcs)->pkcs = &silc_pkcs_list[i];
77 (*new_pkcs)->pkcs->data_context =
78 silc_calloc(1, (*new_pkcs)->pkcs->data_context_len());
79 (*new_pkcs)->context = silc_calloc(1, (*new_pkcs)->pkcs->context_len());
80 (*new_pkcs)->get_key_len = silc_pkcs_get_key_len;
85 /* Free's the PKCS object */
87 void silc_pkcs_free(SilcPKCS pkcs)
90 silc_free(pkcs->context);
93 /* Return TRUE if PKCS algorithm `name' is supported. */
95 int silc_pkcs_is_supported(const unsigned char *name)
99 for (i = 0; silc_pkcs_list[i].name; i++) {
100 if (!strcmp(silc_pkcs_list[i].name, name))
107 /* Returns comma separated list of supported PKCS algorithms */
109 char *silc_pkcs_get_supported()
115 for (i = 0; silc_pkcs_list[i].name; i++) {
116 len += strlen(silc_pkcs_list[i].name);
117 list = silc_realloc(list, len + 1);
119 memcpy(list + (len - strlen(silc_pkcs_list[i].name)),
120 silc_pkcs_list[i].name, strlen(silc_pkcs_list[i].name));
121 memcpy(list + len, ",", 1);
130 /* Returns the length of the key */
132 unsigned int silc_pkcs_get_key_len(SilcPKCS self)
134 return self->key_len;
137 /* Returns SILC style public key */
139 unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, unsigned int *len)
141 return pkcs->pkcs->get_public_key(pkcs->context, len);
144 /* Returns SILC style private key */
146 unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, unsigned int *len)
148 return pkcs->pkcs->get_private_key(pkcs->context, len);
151 /* Sets public key from SilcPublicKey. */
153 int silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
155 return pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
159 /* Sets public key from data. */
161 int silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
164 return pkcs->pkcs->set_public_key(pkcs->context, pk, pk_len);
167 /* Sets private key from SilcPrivateKey. */
169 int silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
171 return pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
172 private_key->prv_len);
175 /* Sets private key from data. */
177 int silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
178 unsigned int prv_len)
180 return pkcs->pkcs->set_private_key(pkcs->context, prv, prv_len);
185 int silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
186 unsigned char *dst, unsigned int *dst_len)
188 return pkcs->pkcs->encrypt(pkcs->context, src, src_len, dst, dst_len);
193 int silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
194 unsigned char *dst, unsigned int *dst_len)
196 return pkcs->pkcs->decrypt(pkcs->context, src, src_len, dst, dst_len);
199 /* Generates signature */
201 int silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
202 unsigned char *dst, unsigned int *dst_len)
204 return pkcs->pkcs->sign(pkcs->context, src, src_len, dst, dst_len);
207 /* Verifies signature */
209 int silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
210 unsigned int signature_len, unsigned char *data,
211 unsigned int data_len)
213 return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
217 /* Generates signature with hash. The hash is signed. */
219 int silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
220 unsigned char *src, unsigned int src_len,
221 unsigned char *dst, unsigned int *dst_len)
223 unsigned char hashr[32];
224 unsigned int hash_len;
227 silc_hash_make(hash, src, src_len, hashr);
228 hash_len = hash->hash->hash_len;
230 ret = pkcs->pkcs->sign(pkcs->context, hashr, hash_len, dst, dst_len);
231 memset(hashr, 0, sizeof(hashr));
236 /* Verifies signature with hash. The `data' is hashed and verified against
239 int silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
240 unsigned char *signature,
241 unsigned int signature_len,
243 unsigned int data_len)
245 unsigned char hashr[32];
246 unsigned int hash_len;
249 silc_hash_make(hash, data, data_len, hashr);
250 hash_len = hash->hash->hash_len;
252 ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
254 memset(hashr, 0, sizeof(hashr));
259 /* Encodes and returns SILC public key identifier. If some of the
260 arguments is NULL those are not encoded into the identifier string.
261 Protocol says that at least username and host must be provided. */
263 char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
264 char *email, char *org, char *country)
268 unsigned int len, tlen = 0;
270 if (!username || !host)
273 len = (username ? strlen(username) : 0) +
274 (host ? strlen(host) : 0) +
275 (realname ? strlen(realname) : 0) +
276 (email ? strlen(email) : 0) +
277 (org ? strlen(org) : 0) +
278 (country ? strlen(country) : 0);
283 len += 3 + 5 + 5 + 4 + 4 + 4;
284 buf = silc_buffer_alloc(len);
285 silc_buffer_pull_tail(buf, len);
288 silc_buffer_format(buf,
289 SILC_STR_UI32_STRING("UN="),
290 SILC_STR_UI32_STRING(username),
292 silc_buffer_pull(buf, 3 + strlen(username));
293 tlen = 3 + strlen(username);
297 silc_buffer_format(buf,
298 SILC_STR_UI32_STRING(", "),
299 SILC_STR_UI32_STRING("HN="),
300 SILC_STR_UI32_STRING(host),
302 silc_buffer_pull(buf, 5 + strlen(host));
303 tlen += 5 + strlen(host);
307 silc_buffer_format(buf,
308 SILC_STR_UI32_STRING(", "),
309 SILC_STR_UI32_STRING("RN="),
310 SILC_STR_UI32_STRING(realname),
312 silc_buffer_pull(buf, 5 + strlen(realname));
313 tlen += 5 + strlen(realname);
317 silc_buffer_format(buf,
318 SILC_STR_UI32_STRING(", "),
319 SILC_STR_UI32_STRING("E="),
320 SILC_STR_UI32_STRING(email),
322 silc_buffer_pull(buf, 4 + strlen(email));
323 tlen += 4 + strlen(email);
327 silc_buffer_format(buf,
328 SILC_STR_UI32_STRING(", "),
329 SILC_STR_UI32_STRING("O="),
330 SILC_STR_UI32_STRING(org),
332 silc_buffer_pull(buf, 4 + strlen(org));
333 tlen += 4 + strlen(org);
337 silc_buffer_format(buf,
338 SILC_STR_UI32_STRING(", "),
339 SILC_STR_UI32_STRING("C="),
340 SILC_STR_UI32_STRING(country),
342 silc_buffer_pull(buf, 4 + strlen(country));
343 tlen += 4 + strlen(country);
346 silc_buffer_push(buf, buf->data - buf->head);
347 identifier = silc_calloc(tlen + 1, sizeof(*identifier));
348 memcpy(identifier, buf->data, tlen);
349 silc_buffer_free(buf);
354 /* Allocates SILC style public key formed from sent arguments. All data
357 SilcPublicKey silc_pkcs_public_key_alloc(char *name, char *identifier,
361 SilcPublicKey public_key;
363 public_key = silc_calloc(1, sizeof(*public_key));
364 public_key->len = 4 + 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
365 public_key->name = strdup(name);
366 public_key->identifier = strdup(identifier);
367 public_key->pk_len = pk_len;
368 public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
369 memcpy(public_key->pk, pk, pk_len);
374 /* Free's public key */
376 void silc_pkcs_public_key_free(SilcPublicKey public_key)
379 silc_free(public_key->name);
380 silc_free(public_key->identifier);
381 silc_free(public_key->pk);
382 silc_free(public_key);
386 /* Allocates SILC private key formed from sent arguments. All data is
389 SilcPrivateKey silc_pkcs_private_key_alloc(char *name, unsigned char *prv,
390 unsigned int prv_len)
392 SilcPrivateKey private_key;
394 private_key = silc_calloc(1, sizeof(*private_key));
395 private_key->name = strdup(name);
396 private_key->prv_len = prv_len;
397 private_key->prv = silc_calloc(prv_len, sizeof(*private_key->prv));
398 memcpy(private_key->prv, prv, prv_len);
403 /* Free's private key */
405 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
408 silc_free(private_key->name);
409 silc_free(private_key->prv);
410 silc_free(private_key);
414 /* Encodes SILC style public key from SilcPublicKey. Returns the encoded
418 silc_pkcs_public_key_encode(SilcPublicKey public_key, unsigned int *len)
423 buf = silc_buffer_alloc(public_key->len);
424 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
426 silc_buffer_format(buf,
427 SILC_STR_UI_INT(public_key->len),
428 SILC_STR_UI_SHORT(strlen(public_key->name)),
429 SILC_STR_UI32_STRING(public_key->name),
430 SILC_STR_UI_SHORT(strlen(public_key->identifier)),
431 SILC_STR_UI32_STRING(public_key->identifier),
432 SILC_STR_UI_XNSTRING(public_key->pk,
436 *len = public_key->len;
438 ret = silc_calloc(buf->len, sizeof(*ret));
439 memcpy(ret, buf->data, buf->len);
440 silc_buffer_free(buf);
445 /* Encodes SILC style public key. Returns the encoded data. */
448 silc_pkcs_public_key_data_encode(unsigned char *pk, unsigned int pk_len,
449 char *pkcs, char *identifier,
456 totlen = 4 + 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
457 buf = silc_buffer_alloc(totlen);
458 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
460 silc_buffer_format(buf,
461 SILC_STR_UI_INT(totlen),
462 SILC_STR_UI_SHORT(strlen(pkcs)),
463 SILC_STR_UI32_STRING(pkcs),
464 SILC_STR_UI_SHORT(strlen(identifier)),
465 SILC_STR_UI32_STRING(identifier),
466 SILC_STR_UI_XNSTRING(pk, pk_len),
471 ret = silc_calloc(buf->len, sizeof(*ret));
472 memcpy(ret, buf->data, buf->len);
473 silc_buffer_free(buf);
478 /* Decodes SILC style public key. Returns TRUE if the decoding was
479 successful. Allocates new public key as well. */
481 int silc_pkcs_public_key_decode(unsigned char *data, unsigned int data_len,
482 SilcPublicKey *public_key)
486 unsigned short pkcs_len, identifier_len;
487 unsigned int totlen, key_len;
488 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
491 buf = silc_buffer_alloc(data_len);
492 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
493 silc_buffer_put(buf, data, data_len);
496 ret = silc_buffer_unformat(buf,
497 SILC_STR_UI_INT(&totlen),
500 silc_buffer_free(buf);
504 if (totlen != data_len) {
505 silc_buffer_free(buf);
509 /* Get algorithm name and identifier */
510 silc_buffer_pull(buf, 4);
512 silc_buffer_unformat(buf,
513 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
514 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
519 if (pkcs_len < 1 || identifier_len < 3 ||
520 pkcs_len + identifier_len > totlen)
523 /* See if we support this algorithm */
524 if (!silc_pkcs_is_supported(pkcs_name))
527 /* Protocol says that at least UN and HN must be provided as identifier,
529 if (!strstr(ident, "UN=") && !strstr(ident, "HN="))
532 /* Get key data. We assume that rest of the buffer is key data. */
533 silc_buffer_pull(buf, 2 + pkcs_len + 2 + identifier_len);
535 ret = silc_buffer_unformat(buf,
536 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
541 /* Try to set the key. If this fails the key must be malformed. This
542 code assumes that the PKCS routine checks the format of the key. */
543 silc_pkcs_alloc(pkcs_name, &alg);
544 if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
549 *public_key = silc_calloc(1, sizeof(**public_key));
550 (*public_key)->len = totlen;
551 (*public_key)->name = pkcs_name;
552 (*public_key)->identifier = ident;
553 (*public_key)->pk = key_data;
554 (*public_key)->pk_len = key_len;
557 silc_buffer_free(buf);
562 silc_free(pkcs_name);
567 silc_buffer_free(buf);
571 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
574 silc_pkcs_private_key_encode(SilcPrivateKey private_key, unsigned int *len)
580 totlen = 2 + strlen(private_key->name) + private_key->prv_len;
581 buf = silc_buffer_alloc(totlen);
582 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
584 silc_buffer_format(buf,
585 SILC_STR_UI_SHORT(strlen(private_key->name)),
586 SILC_STR_UI32_STRING(private_key->name),
587 SILC_STR_UI_XNSTRING(private_key->prv,
588 private_key->prv_len),
593 ret = silc_calloc(buf->len, sizeof(*ret));
594 memcpy(ret, buf->data, buf->len);
595 silc_buffer_free(buf);
600 /* Encodes SILC private key. Returns the encoded data. */
603 silc_pkcs_private_key_data_encode(unsigned char *prv, unsigned int prv_len,
604 char *pkcs, unsigned int *len)
610 totlen = 2 + strlen(pkcs) + prv_len;
611 buf = silc_buffer_alloc(totlen);
612 silc_buffer_pull_tail(buf, totlen);
614 silc_buffer_format(buf,
615 SILC_STR_UI_SHORT(strlen(pkcs)),
616 SILC_STR_UI32_STRING(pkcs),
617 SILC_STR_UI_XNSTRING(prv, prv_len),
622 ret = silc_calloc(buf->len, sizeof(*ret));
623 memcpy(ret, buf->data, buf->len);
624 silc_buffer_free(buf);
629 /* Decodes SILC style public key. Returns TRUE if the decoding was
630 successful. Allocates new private key as well. */
632 int silc_pkcs_private_key_decode(unsigned char *data, unsigned int data_len,
633 SilcPrivateKey *private_key)
637 unsigned short pkcs_len;
638 unsigned int key_len;
639 unsigned char *pkcs_name = NULL, *key_data = NULL;
642 buf = silc_buffer_alloc(data_len);
643 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
644 silc_buffer_put(buf, data, data_len);
646 /* Get algorithm name and identifier */
648 silc_buffer_unformat(buf,
649 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
654 if (pkcs_len < 1 || pkcs_len > buf->truelen)
657 /* See if we support this algorithm */
658 if (!silc_pkcs_is_supported(pkcs_name))
661 /* Get key data. We assume that rest of the buffer is key data. */
662 silc_buffer_pull(buf, 2 + pkcs_len);
664 ret = silc_buffer_unformat(buf,
665 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
670 /* Try to set the key. If this fails the key must be malformed. This
671 code assumes that the PKCS routine checks the format of the key. */
672 silc_pkcs_alloc(pkcs_name, &alg);
673 if (!alg->pkcs->set_private_key(alg->context, key_data, key_len))
678 *private_key = silc_calloc(1, sizeof(**private_key));
679 (*private_key)->name = pkcs_name;
680 (*private_key)->prv = key_data;
681 (*private_key)->prv_len = key_len;
684 silc_buffer_free(buf);
689 silc_free(pkcs_name);
692 silc_buffer_free(buf);
696 /* Internal routine to save public key */
698 static int silc_pkcs_save_public_key_internal(char *filename,
700 unsigned int data_len,
701 unsigned int encoding)
707 case SILC_PKCS_FILE_BIN:
709 case SILC_PKCS_FILE_PEM:
710 data = silc_encode_pem_file(data, data_len);
711 data_len = strlen(data);
715 len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
716 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
717 buf = silc_buffer_alloc(len);
718 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
720 silc_buffer_format(buf,
721 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
722 SILC_STR_UI_XNSTRING(data, data_len),
723 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
727 if (silc_file_write(filename, buf->data, buf->len)) {
728 silc_buffer_free(buf);
732 silc_buffer_free(buf);
736 /* Saves public key into file */
738 int silc_pkcs_save_public_key(char *filename, SilcPublicKey public_key,
739 unsigned int encoding)
742 unsigned int data_len;
744 data = silc_pkcs_public_key_encode(public_key, &data_len);
745 return silc_pkcs_save_public_key_internal(filename, data, data_len,
749 /* Saves public key into file */
751 int silc_pkcs_save_public_key_data(char *filename, unsigned char *data,
752 unsigned int data_len,
753 unsigned int encoding)
755 return silc_pkcs_save_public_key_internal(filename, data, data_len,
759 /* Internal routine to save private key. */
761 static int silc_pkcs_save_private_key_internal(char *filename,
763 unsigned int data_len,
764 unsigned int encoding)
770 case SILC_PKCS_FILE_BIN:
772 case SILC_PKCS_FILE_PEM:
773 data = silc_encode_pem_file(data, data_len);
774 data_len = strlen(data);
778 len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
779 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
780 buf = silc_buffer_alloc(len);
781 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
783 silc_buffer_format(buf,
784 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
785 SILC_STR_UI_XNSTRING(data, data_len),
786 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
789 /* Save into a file */
790 if (silc_file_write_mode(filename, buf->data, buf->len, 0600)) {
791 silc_buffer_free(buf);
795 silc_buffer_free(buf);
799 /* Saves private key into file. */
800 /* XXX The buffer should be encrypted if passphrase is provided. */
802 int silc_pkcs_save_private_key(char *filename, SilcPrivateKey private_key,
803 unsigned char *passphrase,
804 unsigned int encoding)
807 unsigned int data_len;
809 data = silc_pkcs_private_key_encode(private_key, &data_len);
810 return silc_pkcs_save_private_key_internal(filename, data, data_len,
814 /* Saves private key into file. */
815 /* XXX The buffer should be encrypted if passphrase is provided. */
817 int silc_pkcs_save_private_key_data(char *filename, unsigned char *data,
818 unsigned int data_len,
819 unsigned char *passphrase,
820 unsigned int encoding)
822 return silc_pkcs_save_private_key_internal(filename, data, data_len,
826 /* Loads public key from file and allocates new public key. Returns TRUE
827 is loading was successful. */
829 int silc_pkcs_load_public_key(char *filename, SilcPublicKey *public_key,
830 unsigned int encoding)
832 unsigned char *cp, *old, *data, byte;
833 unsigned int i, data_len, len;
835 old = data = silc_file_read(filename, &data_len);
839 /* Check start of file and remove header from the data. */
840 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
842 for (i = 0; i < len; i++) {
845 if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
846 memset(old, 0, data_len);
852 /* Decode public key */
854 len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
855 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
858 case SILC_PKCS_FILE_BIN:
860 case SILC_PKCS_FILE_PEM:
861 data = silc_decode_pem(data, len, &len);
865 if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
866 memset(old, 0, data_len);
872 memset(old, 0, data_len);
877 /* Load private key from file and allocates new private key. Returns TRUE
878 if loading was successful. */
879 /* XXX Should support encrypted private key files */
881 int silc_pkcs_load_private_key(char *filename, SilcPrivateKey *private_key,
882 unsigned int encoding)
884 unsigned char *cp, *old, *data, byte;
885 unsigned int i, data_len, len;
887 old = data = silc_file_read(filename, &data_len);
891 /* Check start of file and remove header from the data. */
892 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
894 for (i = 0; i < len; i++) {
897 if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
898 memset(old, 0, data_len);
904 /* Decode private key */
906 len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
907 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
910 case SILC_PKCS_FILE_BIN:
912 case SILC_PKCS_FILE_PEM:
913 data = silc_decode_pem(data, len, &len);
917 if (!data || !silc_pkcs_private_key_decode(data, len, private_key)) {
918 memset(old, 0, data_len);
924 memset(old, 0, data_len);