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)
102 for (i = 0; silc_pkcs_list[i].name; i++) {
103 if (!strcmp(silc_pkcs_list[i].name, name))
110 /* Returns comma separated list of supported PKCS algorithms */
112 char *silc_pkcs_get_supported()
118 for (i = 0; silc_pkcs_list[i].name; i++) {
119 len += strlen(silc_pkcs_list[i].name);
120 list = silc_realloc(list, len + 1);
122 memcpy(list + (len - strlen(silc_pkcs_list[i].name)),
123 silc_pkcs_list[i].name, strlen(silc_pkcs_list[i].name));
124 memcpy(list + len, ",", 1);
133 /* Returns the length of the key */
135 unsigned int silc_pkcs_get_key_len(SilcPKCS self)
137 return self->key_len;
140 /* Returns SILC style public key */
142 unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, unsigned int *len)
144 return pkcs->pkcs->get_public_key(pkcs->context, len);
147 /* Returns SILC style private key */
149 unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, unsigned int *len)
151 return pkcs->pkcs->get_private_key(pkcs->context, len);
154 /* Sets public key from SilcPublicKey. */
156 int silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
158 return pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
162 /* Sets public key from data. */
164 int silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
167 return pkcs->pkcs->set_public_key(pkcs->context, pk, pk_len);
170 /* Sets private key from SilcPrivateKey. */
172 int silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
174 return pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
175 private_key->prv_len);
178 /* Sets private key from data. */
180 int silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
181 unsigned int prv_len)
183 return pkcs->pkcs->set_private_key(pkcs->context, prv, prv_len);
188 int silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
189 unsigned char *dst, unsigned int *dst_len)
191 return pkcs->pkcs->encrypt(pkcs->context, src, src_len, dst, dst_len);
196 int silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
197 unsigned char *dst, unsigned int *dst_len)
199 return pkcs->pkcs->decrypt(pkcs->context, src, src_len, dst, dst_len);
202 /* Generates signature */
204 int silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, unsigned int src_len,
205 unsigned char *dst, unsigned int *dst_len)
207 return pkcs->pkcs->sign(pkcs->context, src, src_len, dst, dst_len);
210 /* Verifies signature */
212 int silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
213 unsigned int signature_len, unsigned char *data,
214 unsigned int data_len)
216 return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
220 /* Generates signature with hash. The hash is signed. */
222 int silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
223 unsigned char *src, unsigned int src_len,
224 unsigned char *dst, unsigned int *dst_len)
226 unsigned char hashr[32];
227 unsigned int hash_len;
230 silc_hash_make(hash, src, src_len, hashr);
231 hash_len = hash->hash->hash_len;
233 ret = pkcs->pkcs->sign(pkcs->context, hashr, hash_len, dst, dst_len);
234 memset(hashr, 0, sizeof(hashr));
239 /* Verifies signature with hash. The `data' is hashed and verified against
242 int silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
243 unsigned char *signature,
244 unsigned int signature_len,
246 unsigned int data_len)
248 unsigned char hashr[32];
249 unsigned int hash_len;
252 silc_hash_make(hash, data, data_len, hashr);
253 hash_len = hash->hash->hash_len;
255 ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
257 memset(hashr, 0, sizeof(hashr));
262 /* Encodes and returns SILC public key identifier. If some of the
263 arguments is NULL those are not encoded into the identifier string.
264 Protocol says that at least username and host must be provided. */
266 char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
267 char *email, char *org, char *country)
271 unsigned int len, tlen = 0;
273 if (!username || !host)
276 len = (username ? strlen(username) : 0) +
277 (host ? strlen(host) : 0) +
278 (realname ? strlen(realname) : 0) +
279 (email ? strlen(email) : 0) +
280 (org ? strlen(org) : 0) +
281 (country ? strlen(country) : 0);
286 len += 3 + 5 + 5 + 4 + 4 + 4;
287 buf = silc_buffer_alloc(len);
288 silc_buffer_pull_tail(buf, len);
291 silc_buffer_format(buf,
292 SILC_STR_UI32_STRING("UN="),
293 SILC_STR_UI32_STRING(username),
295 silc_buffer_pull(buf, 3 + strlen(username));
296 tlen = 3 + strlen(username);
300 silc_buffer_format(buf,
301 SILC_STR_UI32_STRING(", "),
302 SILC_STR_UI32_STRING("HN="),
303 SILC_STR_UI32_STRING(host),
305 silc_buffer_pull(buf, 5 + strlen(host));
306 tlen += 5 + strlen(host);
310 silc_buffer_format(buf,
311 SILC_STR_UI32_STRING(", "),
312 SILC_STR_UI32_STRING("RN="),
313 SILC_STR_UI32_STRING(realname),
315 silc_buffer_pull(buf, 5 + strlen(realname));
316 tlen += 5 + strlen(realname);
320 silc_buffer_format(buf,
321 SILC_STR_UI32_STRING(", "),
322 SILC_STR_UI32_STRING("E="),
323 SILC_STR_UI32_STRING(email),
325 silc_buffer_pull(buf, 4 + strlen(email));
326 tlen += 4 + strlen(email);
330 silc_buffer_format(buf,
331 SILC_STR_UI32_STRING(", "),
332 SILC_STR_UI32_STRING("O="),
333 SILC_STR_UI32_STRING(org),
335 silc_buffer_pull(buf, 4 + strlen(org));
336 tlen += 4 + strlen(org);
340 silc_buffer_format(buf,
341 SILC_STR_UI32_STRING(", "),
342 SILC_STR_UI32_STRING("C="),
343 SILC_STR_UI32_STRING(country),
345 silc_buffer_pull(buf, 4 + strlen(country));
346 tlen += 4 + strlen(country);
349 silc_buffer_push(buf, buf->data - buf->head);
350 identifier = silc_calloc(tlen + 1, sizeof(*identifier));
351 memcpy(identifier, buf->data, tlen);
352 silc_buffer_free(buf);
357 /* Allocates SILC style public key formed from sent arguments. All data
360 SilcPublicKey silc_pkcs_public_key_alloc(char *name, char *identifier,
364 SilcPublicKey public_key;
366 public_key = silc_calloc(1, sizeof(*public_key));
367 public_key->len = 4 + 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
368 public_key->name = strdup(name);
369 public_key->identifier = strdup(identifier);
370 public_key->pk_len = pk_len;
371 public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
372 memcpy(public_key->pk, pk, pk_len);
377 /* Free's public key */
379 void silc_pkcs_public_key_free(SilcPublicKey public_key)
382 silc_free(public_key->name);
383 silc_free(public_key->identifier);
384 silc_free(public_key->pk);
385 silc_free(public_key);
389 /* Allocates SILC private key formed from sent arguments. All data is
392 SilcPrivateKey silc_pkcs_private_key_alloc(char *name, unsigned char *prv,
393 unsigned int prv_len)
395 SilcPrivateKey private_key;
397 private_key = silc_calloc(1, sizeof(*private_key));
398 private_key->name = strdup(name);
399 private_key->prv_len = prv_len;
400 private_key->prv = silc_calloc(prv_len, sizeof(*private_key->prv));
401 memcpy(private_key->prv, prv, prv_len);
406 /* Free's private key */
408 void silc_pkcs_private_key_free(SilcPrivateKey private_key)
411 silc_free(private_key->name);
412 silc_free(private_key->prv);
413 silc_free(private_key);
417 /* Encodes SILC style public key from SilcPublicKey. Returns the encoded
421 silc_pkcs_public_key_encode(SilcPublicKey public_key, unsigned int *len)
426 buf = silc_buffer_alloc(public_key->len);
427 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
429 silc_buffer_format(buf,
430 SILC_STR_UI_INT(public_key->len),
431 SILC_STR_UI_SHORT(strlen(public_key->name)),
432 SILC_STR_UI32_STRING(public_key->name),
433 SILC_STR_UI_SHORT(strlen(public_key->identifier)),
434 SILC_STR_UI32_STRING(public_key->identifier),
435 SILC_STR_UI_XNSTRING(public_key->pk,
439 *len = public_key->len;
441 ret = silc_calloc(buf->len, sizeof(*ret));
442 memcpy(ret, buf->data, buf->len);
443 silc_buffer_free(buf);
448 /* Encodes SILC style public key. Returns the encoded data. */
451 silc_pkcs_public_key_data_encode(unsigned char *pk, unsigned int pk_len,
452 char *pkcs, char *identifier,
459 totlen = 4 + 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
460 buf = silc_buffer_alloc(totlen);
461 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
463 silc_buffer_format(buf,
464 SILC_STR_UI_INT(totlen),
465 SILC_STR_UI_SHORT(strlen(pkcs)),
466 SILC_STR_UI32_STRING(pkcs),
467 SILC_STR_UI_SHORT(strlen(identifier)),
468 SILC_STR_UI32_STRING(identifier),
469 SILC_STR_UI_XNSTRING(pk, pk_len),
474 ret = silc_calloc(buf->len, sizeof(*ret));
475 memcpy(ret, buf->data, buf->len);
476 silc_buffer_free(buf);
481 /* Decodes SILC style public key. Returns TRUE if the decoding was
482 successful. Allocates new public key as well. */
484 int silc_pkcs_public_key_decode(unsigned char *data, unsigned int data_len,
485 SilcPublicKey *public_key)
489 unsigned short pkcs_len, identifier_len;
490 unsigned int totlen, key_len;
491 unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
494 buf = silc_buffer_alloc(data_len);
495 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
496 silc_buffer_put(buf, data, data_len);
499 ret = silc_buffer_unformat(buf,
500 SILC_STR_UI_INT(&totlen),
503 silc_buffer_free(buf);
507 if (totlen != data_len) {
508 silc_buffer_free(buf);
512 /* Get algorithm name and identifier */
513 silc_buffer_pull(buf, 4);
515 silc_buffer_unformat(buf,
516 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
517 SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
522 if (pkcs_len < 1 || identifier_len < 3 ||
523 pkcs_len + identifier_len > totlen)
526 /* See if we support this algorithm */
527 if (!silc_pkcs_is_supported(pkcs_name))
530 /* Protocol says that at least UN and HN must be provided as identifier,
532 if (!strstr(ident, "UN=") && !strstr(ident, "HN="))
535 /* Get key data. We assume that rest of the buffer is key data. */
536 silc_buffer_pull(buf, 2 + pkcs_len + 2 + identifier_len);
538 ret = silc_buffer_unformat(buf,
539 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
544 /* Try to set the key. If this fails the key must be malformed. This
545 code assumes that the PKCS routine checks the format of the key. */
546 silc_pkcs_alloc(pkcs_name, &alg);
547 if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
552 *public_key = silc_calloc(1, sizeof(**public_key));
553 (*public_key)->len = totlen;
554 (*public_key)->name = pkcs_name;
555 (*public_key)->identifier = ident;
556 (*public_key)->pk = key_data;
557 (*public_key)->pk_len = key_len;
560 silc_buffer_free(buf);
565 silc_free(pkcs_name);
570 silc_buffer_free(buf);
574 /* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
577 silc_pkcs_private_key_encode(SilcPrivateKey private_key, unsigned int *len)
583 totlen = 2 + strlen(private_key->name) + private_key->prv_len;
584 buf = silc_buffer_alloc(totlen);
585 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
587 silc_buffer_format(buf,
588 SILC_STR_UI_SHORT(strlen(private_key->name)),
589 SILC_STR_UI32_STRING(private_key->name),
590 SILC_STR_UI_XNSTRING(private_key->prv,
591 private_key->prv_len),
596 ret = silc_calloc(buf->len, sizeof(*ret));
597 memcpy(ret, buf->data, buf->len);
598 silc_buffer_free(buf);
603 /* Encodes SILC private key. Returns the encoded data. */
606 silc_pkcs_private_key_data_encode(unsigned char *prv, unsigned int prv_len,
607 char *pkcs, unsigned int *len)
613 totlen = 2 + strlen(pkcs) + prv_len;
614 buf = silc_buffer_alloc(totlen);
615 silc_buffer_pull_tail(buf, totlen);
617 silc_buffer_format(buf,
618 SILC_STR_UI_SHORT(strlen(pkcs)),
619 SILC_STR_UI32_STRING(pkcs),
620 SILC_STR_UI_XNSTRING(prv, prv_len),
625 ret = silc_calloc(buf->len, sizeof(*ret));
626 memcpy(ret, buf->data, buf->len);
627 silc_buffer_free(buf);
632 /* Decodes SILC style public key. Returns TRUE if the decoding was
633 successful. Allocates new private key as well. */
635 int silc_pkcs_private_key_decode(unsigned char *data, unsigned int data_len,
636 SilcPrivateKey *private_key)
640 unsigned short pkcs_len;
641 unsigned int key_len;
642 unsigned char *pkcs_name = NULL, *key_data = NULL;
645 buf = silc_buffer_alloc(data_len);
646 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
647 silc_buffer_put(buf, data, data_len);
649 /* Get algorithm name and identifier */
651 silc_buffer_unformat(buf,
652 SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
657 if (pkcs_len < 1 || pkcs_len > buf->truelen)
660 /* See if we support this algorithm */
661 if (!silc_pkcs_is_supported(pkcs_name))
664 /* Get key data. We assume that rest of the buffer is key data. */
665 silc_buffer_pull(buf, 2 + pkcs_len);
667 ret = silc_buffer_unformat(buf,
668 SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
673 /* Try to set the key. If this fails the key must be malformed. This
674 code assumes that the PKCS routine checks the format of the key. */
675 silc_pkcs_alloc(pkcs_name, &alg);
676 if (!alg->pkcs->set_private_key(alg->context, key_data, key_len))
681 *private_key = silc_calloc(1, sizeof(**private_key));
682 (*private_key)->name = pkcs_name;
683 (*private_key)->prv = key_data;
684 (*private_key)->prv_len = key_len;
687 silc_buffer_free(buf);
692 silc_free(pkcs_name);
695 silc_buffer_free(buf);
699 /* Internal routine to save public key */
701 static int silc_pkcs_save_public_key_internal(char *filename,
703 unsigned int data_len,
704 unsigned int encoding)
710 case SILC_PKCS_FILE_BIN:
712 case SILC_PKCS_FILE_PEM:
713 data = silc_encode_pem_file(data, data_len);
714 data_len = strlen(data);
718 len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
719 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
720 buf = silc_buffer_alloc(len);
721 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
723 silc_buffer_format(buf,
724 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
725 SILC_STR_UI_XNSTRING(data, data_len),
726 SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
730 if (silc_file_write(filename, buf->data, buf->len)) {
731 silc_buffer_free(buf);
735 silc_buffer_free(buf);
739 /* Saves public key into file */
741 int silc_pkcs_save_public_key(char *filename, SilcPublicKey public_key,
742 unsigned int encoding)
745 unsigned int data_len;
747 data = silc_pkcs_public_key_encode(public_key, &data_len);
748 return silc_pkcs_save_public_key_internal(filename, data, data_len,
752 /* Saves public key into file */
754 int silc_pkcs_save_public_key_data(char *filename, unsigned char *data,
755 unsigned int data_len,
756 unsigned int encoding)
758 return silc_pkcs_save_public_key_internal(filename, data, data_len,
762 /* Internal routine to save private key. */
764 static int silc_pkcs_save_private_key_internal(char *filename,
766 unsigned int data_len,
767 unsigned int encoding)
773 case SILC_PKCS_FILE_BIN:
775 case SILC_PKCS_FILE_PEM:
776 data = silc_encode_pem_file(data, data_len);
777 data_len = strlen(data);
781 len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
782 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
783 buf = silc_buffer_alloc(len);
784 silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
786 silc_buffer_format(buf,
787 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
788 SILC_STR_UI_XNSTRING(data, data_len),
789 SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
792 /* Save into a file */
793 if (silc_file_write_mode(filename, buf->data, buf->len, 0600)) {
794 silc_buffer_free(buf);
798 silc_buffer_free(buf);
802 /* Saves private key into file. */
803 /* XXX The buffer should be encrypted if passphrase is provided. */
805 int silc_pkcs_save_private_key(char *filename, SilcPrivateKey private_key,
806 unsigned char *passphrase,
807 unsigned int encoding)
810 unsigned int data_len;
812 data = silc_pkcs_private_key_encode(private_key, &data_len);
813 return silc_pkcs_save_private_key_internal(filename, data, data_len,
817 /* Saves private key into file. */
818 /* XXX The buffer should be encrypted if passphrase is provided. */
820 int silc_pkcs_save_private_key_data(char *filename, unsigned char *data,
821 unsigned int data_len,
822 unsigned char *passphrase,
823 unsigned int encoding)
825 return silc_pkcs_save_private_key_internal(filename, data, data_len,
829 /* Loads public key from file and allocates new public key. Returns TRUE
830 is loading was successful. */
832 int silc_pkcs_load_public_key(char *filename, SilcPublicKey *public_key,
833 unsigned int encoding)
835 unsigned char *cp, *old, *data, byte;
836 unsigned int i, data_len, len;
838 old = data = silc_file_read(filename, &data_len);
842 /* Check start of file and remove header from the data. */
843 len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
845 for (i = 0; i < len; i++) {
848 if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
849 memset(old, 0, data_len);
855 /* Decode public key */
857 len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
858 strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
861 case SILC_PKCS_FILE_BIN:
863 case SILC_PKCS_FILE_PEM:
864 data = silc_decode_pem(data, len, &len);
868 if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
869 memset(old, 0, data_len);
875 memset(old, 0, data_len);
880 /* Load private key from file and allocates new private key. Returns TRUE
881 if loading was successful. */
882 /* XXX Should support encrypted private key files */
884 int silc_pkcs_load_private_key(char *filename, SilcPrivateKey *private_key,
885 unsigned int encoding)
887 unsigned char *cp, *old, *data, byte;
888 unsigned int i, data_len, len;
890 old = data = silc_file_read(filename, &data_len);
894 /* Check start of file and remove header from the data. */
895 len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
897 for (i = 0; i < len; i++) {
900 if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
901 memset(old, 0, data_len);
907 /* Decode private key */
909 len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
910 strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
913 case SILC_PKCS_FILE_BIN:
915 case SILC_PKCS_FILE_PEM:
916 data = silc_decode_pem(data, len, &len);
920 if (!data || !silc_pkcs_private_key_decode(data, len, private_key)) {
921 memset(old, 0, data_len);
927 memset(old, 0, data_len);