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) */
34 { "rsa", &silc_rsa_data_context,
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_rsa_data_context_len, silc_rsa_set_arg,
39 silc_pkcs1_encrypt, silc_pkcs1_decrypt,
40 silc_pkcs1_sign, silc_pkcs1_verify },
43 /* Raw RSA operations */
44 { "rsa", &silc_rsa_data_context,
45 silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
46 silc_rsa_get_private_key, silc_rsa_set_public_key,
47 silc_rsa_set_private_key, silc_rsa_context_len,
48 silc_rsa_data_context_len, silc_rsa_set_arg,
49 silc_rsa_encrypt, silc_rsa_decrypt,
50 silc_rsa_sign, silc_rsa_verify },
52 { NULL, NULL, NULL, NULL, NULL,
53 NULL, NULL, NULL, NULL, NULL, NULL }
56 /* Allocates a new SilcPKCS object. The new allocated object is returned
57 to the 'new_pkcs' argument. This function also initializes the data
58 context structure. Function returns 1 on success and 0 on error.
61 int silc_pkcs_alloc(const unsigned char *name, SilcPKCS *new_pkcs)
65 SILC_LOG_DEBUG(("Allocating new PKCS object"));
67 for (i = 0; silc_pkcs_list[i].name; i++) {
68 if (!strcmp(silc_pkcs_list[i].name, name))
72 if (silc_pkcs_list[i].name == NULL)
75 *new_pkcs = silc_calloc(1, sizeof(**new_pkcs));
77 /* Set the pointers */
78 (*new_pkcs)->pkcs = &silc_pkcs_list[i];
79 (*new_pkcs)->pkcs->data_context =
80 silc_calloc(1, (*new_pkcs)->pkcs->data_context_len());
81 (*new_pkcs)->context = silc_calloc(1, (*new_pkcs)->pkcs->context_len());
82 (*new_pkcs)->get_key_len = silc_pkcs_get_key_len;
87 /* Free's the PKCS object */
89 void silc_pkcs_free(SilcPKCS pkcs)
92 silc_free(pkcs->context);
95 /* Return TRUE if PKCS algorithm `name' is supported. */
97 int silc_pkcs_is_supported(const unsigned char *name)
101 for (i = 0; silc_pkcs_list[i].name; i++) {
102 if (!strcmp(silc_pkcs_list[i].name, name))
109 /* Returns comma separated list of supported PKCS algorithms */
111 char *silc_pkcs_get_supported()
117 for (i = 0; silc_pkcs_list[i].name; i++) {
118 len += strlen(silc_pkcs_list[i].name);
119 list = silc_realloc(list, len + 1);
121 memcpy(list + (len - strlen(silc_pkcs_list[i].name)),
122 silc_pkcs_list[i].name, strlen(silc_pkcs_list[i].name));
123 memcpy(list + len, ",", 1);
132 /* Returns the length of the key */
134 unsigned int silc_pkcs_get_key_len(SilcPKCS self)
136 return self->key_len;
139 /* Returns SILC style public key */
141 unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, unsigned int *len)
143 return pkcs->pkcs->get_public_key(pkcs->context, len);
146 /* Returns SILC style private key */
148 unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, unsigned int *len)
150 return pkcs->pkcs->get_private_key(pkcs->context, len);
153 /* Sets public key from SilcPublicKey. */
155 int silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
157 return pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
161 /* Sets public key from data. */
163 int silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
166 return pkcs->pkcs->set_public_key(pkcs->context, pk, pk_len);
169 /* Sets private key from SilcPrivateKey. */
171 int silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
173 return pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
174 private_key->prv_len);
177 /* Sets private key from data. */
179 int silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
180 unsigned int prv_len)
182 return pkcs->pkcs->set_private_key(pkcs->context, prv, prv_len);
187 int silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
188 unsigned char *dst, unsigned int *dst_len)
190 return pkcs->pkcs->encrypt(pkcs->context, src, src_len, dst, dst_len);
195 int silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
196 unsigned char *dst, unsigned int *dst_len)
198 return pkcs->pkcs->decrypt(pkcs->context, src, src_len, dst, dst_len);
201 /* Generates signature */
203 int silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
204 unsigned char *dst, unsigned int *dst_len)
206 return pkcs->pkcs->sign(pkcs->context, src, src_len, dst, dst_len);
209 /* Verifies signature */
211 int silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
212 unsigned int signature_len, unsigned char *data,
213 unsigned int data_len)
215 return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
219 /* Generates signature with hash. The hash is signed. */
221 int silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
222 unsigned char *src, unsigned int src_len,
223 unsigned char *dst, unsigned int *dst_len)
225 unsigned char hashr[32];
226 unsigned int hash_len;
229 silc_hash_make(hash, src, src_len, hashr);
230 hash_len = hash->hash->hash_len;
232 ret = pkcs->pkcs->sign(pkcs->context, hashr, hash_len, dst, dst_len);
233 memset(hashr, 0, sizeof(hashr));
238 /* Verifies signature with hash. The `data' is hashed and verified against
241 int silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
242 unsigned char *signature,
243 unsigned int signature_len,
245 unsigned int data_len)
247 unsigned char hashr[32];
248 unsigned int hash_len;
251 silc_hash_make(hash, data, data_len, hashr);
252 hash_len = hash->hash->hash_len;
254 ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
256 memset(hashr, 0, sizeof(hashr));
261 /* Encodes and returns SILC public key identifier. If some of the
262 arguments is NULL those are not encoded into the identifier string.
263 Protocol says that at least username and host must be provided. */
265 char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
266 char *email, char *org, char *country)
270 unsigned int len, tlen = 0;
272 if (!username || !host)
275 len = (username ? strlen(username) : 0) +
276 (host ? strlen(host) : 0) +
277 (realname ? strlen(realname) : 0) +
278 (email ? strlen(email) : 0) +
279 (org ? strlen(org) : 0) +
280 (country ? strlen(country) : 0);
285 len += 3 + 5 + 5 + 4 + 4 + 4;
286 buf = silc_buffer_alloc(len);
287 silc_buffer_pull_tail(buf, len);
290 silc_buffer_format(buf,
291 SILC_STR_UI32_STRING("UN="),
292 SILC_STR_UI32_STRING(username),
294 silc_buffer_pull(buf, 3 + strlen(username));
295 tlen = 3 + strlen(username);
299 silc_buffer_format(buf,
300 SILC_STR_UI32_STRING(", "),
301 SILC_STR_UI32_STRING("HN="),
302 SILC_STR_UI32_STRING(host),
304 silc_buffer_pull(buf, 5 + strlen(host));
305 tlen += 5 + strlen(host);
309 silc_buffer_format(buf,
310 SILC_STR_UI32_STRING(", "),
311 SILC_STR_UI32_STRING("RN="),
312 SILC_STR_UI32_STRING(realname),
314 silc_buffer_pull(buf, 5 + strlen(realname));
315 tlen += 5 + strlen(realname);
319 silc_buffer_format(buf,
320 SILC_STR_UI32_STRING(", "),
321 SILC_STR_UI32_STRING("E="),
322 SILC_STR_UI32_STRING(email),
324 silc_buffer_pull(buf, 4 + strlen(email));
325 tlen += 4 + strlen(email);
329 silc_buffer_format(buf,
330 SILC_STR_UI32_STRING(", "),
331 SILC_STR_UI32_STRING("O="),
332 SILC_STR_UI32_STRING(org),
334 silc_buffer_pull(buf, 4 + strlen(org));
335 tlen += 4 + strlen(org);
339 silc_buffer_format(buf,
340 SILC_STR_UI32_STRING(", "),
341 SILC_STR_UI32_STRING("C="),
342 SILC_STR_UI32_STRING(country),
344 silc_buffer_pull(buf, 4 + strlen(country));
345 tlen += 4 + strlen(country);
348 silc_buffer_push(buf, buf->data - buf->head);
349 identifier = silc_calloc(tlen + 1, sizeof(*identifier));
350 memcpy(identifier, buf->data, tlen);
351 silc_buffer_free(buf);
356 /* Allocates SILC style public key formed from sent arguments. All data
359 SilcPublicKey silc_pkcs_public_key_alloc(char *name, char *identifier,
363 SilcPublicKey public_key;
365 public_key = silc_calloc(1, sizeof(*public_key));
366 public_key->len = 4 + 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
367 public_key->name = strdup(name);
368 public_key->identifier = strdup(identifier);
369 public_key->pk_len = pk_len;
370 public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
371 memcpy(public_key->pk, pk, pk_len);
376 /* Free's public key */
378 void silc_pkcs_public_key_free(SilcPublicKey public_key)
381 silc_free(public_key->name);
382 silc_free(public_key->identifier);
383 silc_free(public_key->pk);
384 silc_free(public_key);
388 /* Allocates SILC private key formed from sent arguments. All data is
391 SilcPrivateKey silc_pkcs_private_key_alloc(char *name, unsigned char *prv,
392 unsigned int prv_len)
394 SilcPrivateKey private_key;
396 private_key = silc_calloc(1, sizeof(*private_key));
397 private_key->name = strdup(name);
398 private_key->prv_len = prv_len;
399 private_key->prv = silc_calloc(prv_len, sizeof(*private_key->prv));
400 memcpy(private_key->prv, prv, prv_len);
405 /* Free's private key */
407 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
410 silc_free(private_key->name);
411 silc_free(private_key->prv);
412 silc_free(private_key);
416 /* Encodes SILC style public key from SilcPublicKey. Returns the encoded
420 silc_pkcs_public_key_encode(SilcPublicKey public_key, unsigned int *len)
425 buf = silc_buffer_alloc(public_key->len);
426 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
428 silc_buffer_format(buf,
429 SILC_STR_UI_INT(public_key->len),
430 SILC_STR_UI_SHORT(strlen(public_key->name)),
431 SILC_STR_UI32_STRING(public_key->name),
432 SILC_STR_UI_SHORT(strlen(public_key->identifier)),
433 SILC_STR_UI32_STRING(public_key->identifier),
434 SILC_STR_UI_XNSTRING(public_key->pk,
438 *len = public_key->len;
440 ret = silc_calloc(buf->len, sizeof(*ret));
441 memcpy(ret, buf->data, buf->len);
442 silc_buffer_free(buf);
447 /* Encodes SILC style public key. Returns the encoded data. */
450 silc_pkcs_public_key_data_encode(unsigned char *pk, unsigned int pk_len,
451 char *pkcs, char *identifier,
458 totlen = 4 + 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
459 buf = silc_buffer_alloc(totlen);
460 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
462 silc_buffer_format(buf,
463 SILC_STR_UI_INT(totlen),
464 SILC_STR_UI_SHORT(strlen(pkcs)),
465 SILC_STR_UI32_STRING(pkcs),
466 SILC_STR_UI_SHORT(strlen(identifier)),
467 SILC_STR_UI32_STRING(identifier),
468 SILC_STR_UI_XNSTRING(pk, pk_len),
473 ret = silc_calloc(buf->len, sizeof(*ret));
474 memcpy(ret, buf->data, buf->len);
475 silc_buffer_free(buf);
480 /* Decodes SILC style public key. Returns TRUE if the decoding was
481 successful. Allocates new public key as well. */
483 int silc_pkcs_public_key_decode(unsigned char *data, unsigned int data_len,
484 SilcPublicKey *public_key)
488 unsigned short pkcs_len, identifier_len;
489 unsigned int totlen, key_len;
490 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
493 buf = silc_buffer_alloc(data_len);
494 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
495 silc_buffer_put(buf, data, data_len);
498 ret = silc_buffer_unformat(buf,
499 SILC_STR_UI_INT(&totlen),
502 silc_buffer_free(buf);
506 if (totlen != data_len) {
507 silc_buffer_free(buf);
511 /* Get algorithm name and identifier */
512 silc_buffer_pull(buf, 4);
514 silc_buffer_unformat(buf,
515 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
516 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
521 if (pkcs_len < 1 || identifier_len < 3 ||
522 pkcs_len + identifier_len > totlen)
525 /* See if we support this algorithm */
526 if (!silc_pkcs_is_supported(pkcs_name))
529 /* Protocol says that at least UN and HN must be provided as identifier,
531 if (!strstr(ident, "UN=") && !strstr(ident, "HN="))
534 /* Get key data. We assume that rest of the buffer is key data. */
535 silc_buffer_pull(buf, 2 + pkcs_len + 2 + identifier_len);
537 ret = silc_buffer_unformat(buf,
538 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
543 /* Try to set the key. If this fails the key must be malformed. This
544 code assumes that the PKCS routine checks the format of the key. */
545 silc_pkcs_alloc(pkcs_name, &alg);
546 if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
551 *public_key = silc_calloc(1, sizeof(**public_key));
552 (*public_key)->len = totlen;
553 (*public_key)->name = pkcs_name;
554 (*public_key)->identifier = ident;
555 (*public_key)->pk = key_data;
556 (*public_key)->pk_len = key_len;
559 silc_buffer_free(buf);
564 silc_free(pkcs_name);
569 silc_buffer_free(buf);
573 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
576 silc_pkcs_private_key_encode(SilcPrivateKey private_key, unsigned int *len)
582 totlen = 2 + strlen(private_key->name) + private_key->prv_len;
583 buf = silc_buffer_alloc(totlen);
584 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
586 silc_buffer_format(buf,
587 SILC_STR_UI_SHORT(strlen(private_key->name)),
588 SILC_STR_UI32_STRING(private_key->name),
589 SILC_STR_UI_XNSTRING(private_key->prv,
590 private_key->prv_len),
595 ret = silc_calloc(buf->len, sizeof(*ret));
596 memcpy(ret, buf->data, buf->len);
597 silc_buffer_free(buf);
602 /* Encodes SILC private key. Returns the encoded data. */
605 silc_pkcs_private_key_data_encode(unsigned char *prv, unsigned int prv_len,
606 char *pkcs, unsigned int *len)
612 totlen = 2 + strlen(pkcs) + prv_len;
613 buf = silc_buffer_alloc(totlen);
614 silc_buffer_pull_tail(buf, totlen);
616 silc_buffer_format(buf,
617 SILC_STR_UI_SHORT(strlen(pkcs)),
618 SILC_STR_UI32_STRING(pkcs),
619 SILC_STR_UI_XNSTRING(prv, prv_len),
624 ret = silc_calloc(buf->len, sizeof(*ret));
625 memcpy(ret, buf->data, buf->len);
626 silc_buffer_free(buf);
631 /* Decodes SILC style public key. Returns TRUE if the decoding was
632 successful. Allocates new private key as well. */
634 int silc_pkcs_private_key_decode(unsigned char *data, unsigned int data_len,
635 SilcPrivateKey *private_key)
639 unsigned short pkcs_len;
640 unsigned int key_len;
641 unsigned char *pkcs_name = NULL, *key_data = NULL;
644 buf = silc_buffer_alloc(data_len);
645 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
646 silc_buffer_put(buf, data, data_len);
648 /* Get algorithm name and identifier */
650 silc_buffer_unformat(buf,
651 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
656 if (pkcs_len < 1 || pkcs_len > buf->truelen)
659 /* See if we support this algorithm */
660 if (!silc_pkcs_is_supported(pkcs_name))
663 /* Get key data. We assume that rest of the buffer is key data. */
664 silc_buffer_pull(buf, 2 + pkcs_len);
666 ret = silc_buffer_unformat(buf,
667 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
672 /* Try to set the key. If this fails the key must be malformed. This
673 code assumes that the PKCS routine checks the format of the key. */
674 silc_pkcs_alloc(pkcs_name, &alg);
675 if (!alg->pkcs->set_private_key(alg->context, key_data, key_len))
680 *private_key = silc_calloc(1, sizeof(**private_key));
681 (*private_key)->name = pkcs_name;
682 (*private_key)->prv = key_data;
683 (*private_key)->prv_len = key_len;
686 silc_buffer_free(buf);
691 silc_free(pkcs_name);
694 silc_buffer_free(buf);
698 /* Internal routine to save public key */
700 static int silc_pkcs_save_public_key_internal(char *filename,
702 unsigned int data_len,
703 unsigned int encoding)
709 case SILC_PKCS_FILE_BIN:
711 case SILC_PKCS_FILE_PEM:
712 data = silc_encode_pem_file(data, data_len);
713 data_len = strlen(data);
717 len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
718 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
719 buf = silc_buffer_alloc(len);
720 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
722 silc_buffer_format(buf,
723 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
724 SILC_STR_UI_XNSTRING(data, data_len),
725 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
729 if (silc_file_write(filename, buf->data, buf->len)) {
730 silc_buffer_free(buf);
734 silc_buffer_free(buf);
738 /* Saves public key into file */
740 int silc_pkcs_save_public_key(char *filename, SilcPublicKey public_key,
741 unsigned int encoding)
744 unsigned int data_len;
746 data = silc_pkcs_public_key_encode(public_key, &data_len);
747 return silc_pkcs_save_public_key_internal(filename, data, data_len,
751 /* Saves public key into file */
753 int silc_pkcs_save_public_key_data(char *filename, unsigned char *data,
754 unsigned int data_len,
755 unsigned int encoding)
757 return silc_pkcs_save_public_key_internal(filename, data, data_len,
761 /* Internal routine to save private key. */
763 static int silc_pkcs_save_private_key_internal(char *filename,
765 unsigned int data_len,
766 unsigned int encoding)
772 case SILC_PKCS_FILE_BIN:
774 case SILC_PKCS_FILE_PEM:
775 data = silc_encode_pem_file(data, data_len);
776 data_len = strlen(data);
780 len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
781 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
782 buf = silc_buffer_alloc(len);
783 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
785 silc_buffer_format(buf,
786 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
787 SILC_STR_UI_XNSTRING(data, data_len),
788 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
791 /* Save into a file */
792 if (silc_file_write_mode(filename, buf->data, buf->len, 0600)) {
793 silc_buffer_free(buf);
797 silc_buffer_free(buf);
801 /* Saves private key into file. */
802 /* XXX The buffer should be encrypted if passphrase is provided. */
804 int silc_pkcs_save_private_key(char *filename, SilcPrivateKey private_key,
805 unsigned char *passphrase,
806 unsigned int encoding)
809 unsigned int data_len;
811 data = silc_pkcs_private_key_encode(private_key, &data_len);
812 return silc_pkcs_save_private_key_internal(filename, data, data_len,
816 /* Saves private key into file. */
817 /* XXX The buffer should be encrypted if passphrase is provided. */
819 int silc_pkcs_save_private_key_data(char *filename, unsigned char *data,
820 unsigned int data_len,
821 unsigned char *passphrase,
822 unsigned int encoding)
824 return silc_pkcs_save_private_key_internal(filename, data, data_len,
828 /* Loads public key from file and allocates new public key. Returns TRUE
829 is loading was successful. */
831 int silc_pkcs_load_public_key(char *filename, SilcPublicKey *public_key,
832 unsigned int encoding)
834 unsigned char *cp, *old, *data, byte;
835 unsigned int i, data_len, len;
837 old = data = silc_file_read(filename, &data_len);
841 /* Check start of file and remove header from the data. */
842 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
844 for (i = 0; i < len; i++) {
847 if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
848 memset(old, 0, data_len);
854 /* Decode public key */
856 len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
857 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
860 case SILC_PKCS_FILE_BIN:
862 case SILC_PKCS_FILE_PEM:
863 data = silc_decode_pem(data, len, &len);
867 if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
868 memset(old, 0, data_len);
874 memset(old, 0, data_len);
879 /* Load private key from file and allocates new private key. Returns TRUE
880 if loading was successful. */
881 /* XXX Should support encrypted private key files */
883 int silc_pkcs_load_private_key(char *filename, SilcPrivateKey *private_key,
884 unsigned int encoding)
886 unsigned char *cp, *old, *data, byte;
887 unsigned int i, data_len, len;
889 old = data = silc_file_read(filename, &data_len);
893 /* Check start of file and remove header from the data. */
894 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
896 for (i = 0; i < len; i++) {
899 if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
900 memset(old, 0, data_len);
906 /* Decode private key */
908 len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
909 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
912 case SILC_PKCS_FILE_BIN:
914 case SILC_PKCS_FILE_PEM:
915 data = silc_decode_pem(data, len, &len);
919 if (!data || !silc_pkcs_private_key_decode(data, len, private_key)) {
920 memset(old, 0, data_len);
926 memset(old, 0, data_len);