Separated SILC Public Key Payload routines into lib/silccore.
+Sat Dec 30 22:54:21 EET 2005 Pekka Riikonen <priikone@silcnet.org>
+
+ * New SILC PKCS API enabling support for other public keys
+ and certificates, lib/silccrypt/silcpkcs.[ch], silcpk.[ch].
+
+ * Separated SILC Public Key Payload routines from the PKCS API
+ to lib/silccore/silcpubkey.[ch].
+
Wed Dec 28 13:55:22 EET 2005 Pekka Riikonen <priikone@silcnet.org>
* Added SILC Key Repository library, lib/silcskr.
TODO for 1.1 And Beyond
=======================
-lib/silccrypt
+lib/silccrypt ****PARTLY DONE****
=============
o Implement the defined SilcDH API. The definition is in
#include "silchmac.h"
#include "silcrng.h"
#include "silcpkcs.h"
+#include "silcpk.h"
#include "silcpkcs1.h"
/* More SILC util library includes */
#include "silcmode.h"
#include "silcauth.h"
#include "silcattrs.h"
+#include "silcpubkey.h"
#ifdef SILC_DIST_SKR
#include "silcskr.h"
void silc_asn1_uninit(SilcAsn1 asn1)
{
-#if 1
- silc_stack_stats(asn1->stack1);
- silc_stack_stats(asn1->stack2);
-#endif
silc_stack_free(asn1->stack1);
silc_stack_free(asn1->stack2);
}
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2003 - 2005 Pekka Riikonen
+ Copyright (C) 2003 - 2006 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
* pre-allocated SilcStack is used as memory.
*
* The encoding and decoding interface is simple. silc_asn1_encode is used
- * encode and silc_asn1_decode to decode. The actual ASN.1 is defined
+ * to encode and silc_asn1_decode to decode. The actual ASN.1 is defined
* as variable argument list to the function. Various macros can be used
* to encode and decode different ASN.1 types. All types may also be used
* to encode and decode with various options (such as implicit and explicit
* with SILC_ASN1_OPTS macro. Other options can be given with various
* SILC_ASN1_*_T macros.
*
+ * EXAMPLE
+ *
+ * // Encodes boolean value with explicit tag and private class, and
+ * // the result is allocated into `dest'.
+ * silc_asn1_encode(asn1, &dest,
+ * SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
+ * SILC_ASN1_BOOLEAN_T(SILC_ASN1_PRIVATE |
+ * SILC_ASN1_EXPLICIT, 100, boolval),
+ * SILC_ASN1_END);
+ *
* SOURCE
*/
typedef enum {
*
* Decoding:
* SILC_ASN1_ANY(&buffer)
- * SILC_ASN1_ANY_T(opts, tag, &buffer)
+ * SILC_ASN1_ANY_T(opts, tag, buffer)
*
* DESCRIPTION
*
*
* Decoding:
* SILC_ASN1_ANY_PRIMITIVE(tag, &buffer)
- * SILC_ASN1_ANY_PRIMITIVE_T(opts, tag, &buffer)
+ * SILC_ASN1_ANY_PRIMITIVE_T(opts, tag, buffer)
*
* DESCRIPTION
*
*
* Encoding:
* SILC_ASN1_INT(integer)
- * SILC_ASN1_INT_T(opts, tag, integer)
+ * SILC_ASN1_INT_T(opts, tag, &integer)
*
* Decoding:
* SILC_ASN1_INT(&integer)
*
* Encoding:
* SILC_ASN1_ENUM(enum)
- * SILC_ASN1_ENUM_T(opts, tag, enum)
+ * SILC_ASN1_ENUM_T(opts, tag, &enum)
*
* Decoding:
* SILC_ASN1_ENUM(&enum)
*
* Decoding:
* SILC_ASN1_UTC_TIME(&str, &timeval)
- * SILC_ASN1_UTC_TIME_T(opts, tag, &timeval)
+ * SILC_ASN1_UTC_TIME_T(opts, tag, timeval)
*
* DESCRIPTION
*
*
* Decoding:
* SILC_ASN1_GEN_TIME(&str, &timeval)
- * SILC_ASN1_GEN_TIME_T(opts, tag, &timeval)
+ * SILC_ASN1_GEN_TIME_T(opts, tag, timeval)
*
* DESCRIPTION
*
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2003 - 2005 Pekka Riikonen
+ Copyright (C) 2003 - 2006 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "silcasn1.h"
#include "silcber.h"
-
/************************** ASN.1 Decoder routines **************************/
/* Internal SEQUENCE OF and SET OF decoder. This is used only when decoding
/* 2s complement and change sign */
silc_mp_init(&z);
- silc_mp_set(&z, 0);
+ silc_mp_set_ui(&z, 0);
silc_mp_add_ui(*intval, *intval, 1);
silc_mp_sub(*intval, &z, *intval);
silc_mp_uninit(&z);
len = silc_buffer_len(node);
dest = silc_buffer_srealloc_size(stack1, dest,
silc_buffer_truelen(dest) + len);
+ if (!dest)
+ goto fail;
silc_buffer_put(dest, node->data, len);
}
break;
bytes in 1s complement */
} else {
/* Positive */
- len = (silc_mp_sizeinbase(mpint, 2) + 7) / 8;
- len += len & 7 ? 1: 0;
+ len = silc_mp_sizeinbase(mpint, 2);
+ if (!(len & 7))
+ len = ((len + 7) / 8) + 1;
+ else
+ len = (len + 7) / 8;
silc_stack_push(stack2, &frame);
silc_buffer_srealloc_size(stack2, &buf,
silc_buffer_truelen(&buf) + len);
+ buf.data[0] = 0x00;
silc_mp_mp2bin_noalloc(mpint, buf.data, silc_buffer_len(&buf));
}
/* Long form */
/* Calculate the number of octets for the length field */
- tmp = tag;
+ tmp = data_len;
c = 0;
while (tmp) {
c++;
unsigned char *str;
SilcUInt32 str_len;
char tmp[32];
+ SilcRng rng;
+ SilcMPInt mpint, mpint2;
memset(&node, 0, sizeof(node));
memset(&node2, 0, sizeof(node2));
silc_log_set_debug_string("*asn1*,*ber*");
}
+ silc_hash_register_default();
+ rng = silc_rng_alloc();
+ silc_rng_init(rng);
+
SILC_LOG_DEBUG(("Allocating ASN.1 context"));
asn1 = silc_asn1_alloc();
if (!asn1)
memset(&node, 0, sizeof(node));
printf("\n");
+
memset(&node, 0, sizeof(node));
SILC_LOG_DEBUG(("Encoding ASN.1 tree 9"));
success =
SILC_LOG_DEBUG(("Ooctet-string %s, len %d", str, str_len));
printf("\n");
+
+ memset(&node, 0, sizeof(node));
+ SILC_LOG_DEBUG(("Encoding ASN.1 tree 10 (INTEGER)"));
+ str = silc_rng_get_rn_data(rng, 256);
+ silc_mp_init(&mpint);
+ silc_mp_init(&mpint2);
+ silc_mp_bin2mp(str, 256, &mpint);
+ success =
+ silc_asn1_encode(asn1, &node,
+ SILC_ASN1_INT(&mpint),
+ SILC_ASN1_END);
+ if (!success) {
+ SILC_LOG_DEBUG(("Encoding failed"));
+ goto out;
+ }
+ SILC_LOG_DEBUG(("Encoding success"));
+ SILC_LOG_HEXDUMP(("ASN.1 tree"), node.data, silc_buffer_len(&node));
+ SILC_LOG_DEBUG(("Decoding ASN.1 tree 9"));
+ success =
+ silc_asn1_decode(asn1, &node,
+ SILC_ASN1_INT(&mpint2),
+ SILC_ASN1_END);
+ if (silc_mp_cmp(&mpint, &mpint2) != 0) {
+ SILC_LOG_DEBUG(("INTEGER MISMATCH"));
+ goto out;
+ }
+ if (!success) {
+ SILC_LOG_DEBUG(("Decoding failed"));
+ goto out;
+ }
+ SILC_LOG_DEBUG(("Decoding success"));
+ printf("\n");
+
#endif
silc_asn1_free(asn1);
noinst_LTLIBRARIES = libsilccore.la
-libsilccore_la_SOURCES = \
- silcid.c \
- silcidcache.c \
- silcmessage.c \
- silcchannel.c \
- silccommand.c \
- silcpacket.c \
- silcargument.c \
- silcnotify.c \
- silcauth.c \
- silcattrs.c \
- silcstatus.c
+libsilccore_la_SOURCES = \
+ silcid.c \
+ silcidcache.c \
+ silcmessage.c \
+ silcchannel.c \
+ silccommand.c \
+ silcpacket.c \
+ silcargument.c \
+ silcnotify.c \
+ silcauth.c \
+ silcattrs.c \
+ silcstatus.c \
+ silcpubkey.c
#ifdef SILC_DIST_TOOLKIT
include_HEADERS = \
silcpacket.h \
silcargument.h \
silcstatus.h \
- silcattrs.h
+ silcattrs.h \
+ silcpubkey.h
SILC_EXTRA_DIST = tests
#endif SILC_DIST_TOOLKIT
unsigned char *tmp;
SilcUInt32 tmp_len;
SilcBuffer buf;
- SilcPKCS pkcs;
SILC_LOG_DEBUG(("Generating Authentication Payload with data"));
if (!tmp)
return NULL;
- /* Allocate PKCS object */
- if (!silc_pkcs_alloc(private_key->name, SILC_PKCS_SILC, &pkcs)) {
- memset(tmp, 0, tmp_len);
- silc_free(tmp);
- return NULL;
- }
- silc_pkcs_public_key_set(pkcs, public_key);
- silc_pkcs_private_key_set(pkcs, private_key);
-
/* Compute the hash and the signature. */
- if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
- !silc_pkcs_sign_with_hash(pkcs, hash, tmp, tmp_len, auth_data,
- &auth_len)) {
+ if (!silc_pkcs_sign(private_key, tmp, tmp_len, auth_data,
+ sizeof(auth_data) - 1, &auth_len, hash)) {
memset(tmp, 0, tmp_len);
silc_free(tmp);
- silc_pkcs_free(pkcs);
return NULL;
}
memset(tmp, 0, tmp_len);
memset(auth_data, 0, sizeof(auth_data));
silc_free(tmp);
- silc_pkcs_free(pkcs);
return buf;
}
{
unsigned char *tmp;
SilcUInt32 tmp_len;
- SilcPKCS pkcs;
SILC_LOG_DEBUG(("Verifying authentication data"));
return FALSE;
}
- /* Allocate PKCS object */
- if (!silc_pkcs_alloc(public_key->name, SILC_PKCS_SILC, &pkcs)) {
- memset(tmp, 0, tmp_len);
- silc_free(tmp);
- return FALSE;
- }
- silc_pkcs_public_key_set(pkcs, public_key);
-
/* Verify the authentication data */
- if (!silc_pkcs_verify_with_hash(pkcs, hash, payload->auth_data,
- payload->auth_len, tmp, tmp_len)) {
+ if (!silc_pkcs_verify(public_key, payload->auth_data,
+ payload->auth_len, tmp, tmp_len, hash)) {
memset(tmp, 0, tmp_len);
silc_free(tmp);
- silc_pkcs_free(pkcs);
SILC_LOG_DEBUG(("Authentication failed"));
return FALSE;
}
memset(tmp, 0, tmp_len);
silc_free(tmp);
- silc_pkcs_free(pkcs);
SILC_LOG_DEBUG(("Authentication successful"));
SilcHash hash)
{
SilcBuffer buffer, sign;
- SilcPKCS pkcs;
unsigned char auth_data[2048 + 1];
SilcUInt32 auth_len;
unsigned char *pk = NULL;
if (!message_payload || !message_payload_len || !private_key || !hash)
return NULL;
- if (public_key)
+ if (public_key) {
pk = silc_pkcs_public_key_encode(public_key, &pk_len);
-
- /* Now we support only SILC style public key */
- pk_type = SILC_SKE_PK_TYPE_SILC;
+ if (!pk)
+ return NULL;
+ }
+ pk_type = silc_pkcs_get_type(public_key);
/* Encode the data to be signed */
sign = silc_message_signed_encode_data(message_payload,
/* Sign the buffer */
- /* Allocate PKCS object */
- if (!silc_pkcs_alloc(private_key->name, SILC_PKCS_SILC, &pkcs)) {
- SILC_LOG_ERROR(("Could not allocated PKCS"));
- silc_buffer_clear(sign);
- silc_buffer_free(sign);
- silc_free(pk);
- return NULL;
- }
- silc_pkcs_private_key_set(pkcs, private_key);
-
/* Compute the hash and the signature. */
- if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
- !silc_pkcs_sign_with_hash(pkcs, hash, sign->data, silc_buffer_len(sign), auth_data,
- &auth_len)) {
+ if (!silc_pkcs_sign(private_key, sign->data, silc_buffer_len(sign),
+ auth_data, sizeof(auth_data) - 1, &auth_len, hash)) {
SILC_LOG_ERROR(("Could not compute signature"));
silc_buffer_clear(sign);
silc_buffer_free(sign);
- silc_pkcs_free(pkcs);
silc_free(pk);
return NULL;
}
if (!buffer) {
silc_buffer_clear(sign);
silc_buffer_free(sign);
- silc_pkcs_free(pkcs);
memset(auth_data, 0, sizeof(auth_data));
silc_free(pk);
return NULL;
SILC_LOG_HEXDUMP(("sig payload"), buffer->data, silc_buffer_len(buffer));
memset(auth_data, 0, sizeof(auth_data));
- silc_pkcs_free(pkcs);
silc_buffer_clear(sign);
silc_buffer_free(sign);
silc_free(pk);
{
int ret = SILC_AUTH_FAILED;
SilcBuffer sign;
- SilcPKCS pkcs;
SilcBuffer tmp;
if (!sig || !remote_public_key || !hash)
if (!sign)
return ret;
- /* Allocate PKCS object */
- if (!silc_pkcs_alloc(remote_public_key->name, SILC_PKCS_SILC, &pkcs)) {
- silc_buffer_clear(sign);
- silc_buffer_free(sign);
- return ret;
- }
- silc_pkcs_public_key_set(pkcs, remote_public_key);
-
/* Verify the authentication data */
- if (!silc_pkcs_verify_with_hash(pkcs, hash, sig->sign_data,
- sig->sign_len,
- sign->data, silc_buffer_len(sign))) {
+ if (!silc_pkcs_verify(remote_public_key, sig->sign_data,
+ sig->sign_len,
+ sign->data, silc_buffer_len(sign), hash)) {
silc_buffer_clear(sign);
silc_buffer_free(sign);
- silc_pkcs_free(pkcs);
SILC_LOG_DEBUG(("Signature verification failed"));
return ret;
}
silc_buffer_clear(sign);
silc_buffer_free(sign);
- silc_pkcs_free(pkcs);
SILC_LOG_DEBUG(("Signature verification successful"));
SilcPublicKey
silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
- unsigned char **pk_data,
+ const unsigned char **pk_data,
SilcUInt32 *pk_data_len)
{
SilcPublicKey pk;
- if (!sig->pk_data || !silc_pkcs_public_key_decode(sig->pk_data,
- sig->pk_len, &pk))
+ if (!sig->pk_data)
+ return NULL;
+
+ if (!silc_pkcs_public_key_alloc(sig->pk_type, sig->pk_data,
+ sig->pk_len, &pk))
return NULL;
if (pk_data)
/*
- silcmessage.h
+ silcmessage.h
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2002 Pekka Riikonen
+ Copyright (C) 1997 - 2005 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*
* This interface defines also the SILC_MESSAGE_FLAG_SIGNED Payload,
* which defines how channel messages and private messages can be digitally
- * signed. This interface provides the payload parsing, encoding,
+ * signed. This interface provides the payload parsing, encoding,
* signature computing and signature verification routines.
*
***/
/****s* silccore/SilcMessageAPI/SilcMessagePayload
*
* NAME
- *
+ *
* typedef struct SilcMessagePayloadStruct *SilcMessagePayload;
*
*
/****s* silccore/SilcMessageAPI/SilcMessageSignedPayload
*
* NAME
- *
+ *
* typedef struct SilcMessageSignedPayloadStruct *SilcMessageSignedPayload;
*
*
/****d* silccore/SilcMessageAPI/SilcMessageFlags
*
* NAME
- *
+ *
* typedef SilcUInt16 SilcMessageFlags;
*
* DESCRIPTION
*
- * The message flags type definition and the message flags. The
+ * The message flags type definition and the message flags. The
* message flags are used to indicate some status of the message.
*
* SOURCE
*
* This is usually used by the Message Payload interface itself but can
* be called by the appliation if separate decryption process is required.
- * For example server might need to call this directly in some
+ * For example server might need to call this directly in some
* circumstances. The `cipher' is used to decrypt the payload. If
* `check_mac' is FALSE then MAC is not verified.
*
*
* SYNOPSIS
*
- * SilcMessagePayload
+ * SilcMessagePayload
* silc_message_payload_parse(unsigned char *payload,
* SilcUInt32 payload_len,
* SilcBool private_message,
* (no private message key) and this merely decodes the payload.
*
***/
-SilcMessagePayload
+SilcMessagePayload
silc_message_payload_parse(unsigned char *payload,
SilcUInt32 payload_len,
SilcBool private_message,
*
* This is usually used by the Message Payload interface itself but can
* be called by the appliation if separate encryption process is required.
- * For example server might need to call this directly in some
+ * For example server might need to call this directly in some
* circumstances. The `cipher' is used to encrypt the payload and `hmac'
* to compute the MAC for the payload.
*
*
* DESCRIPTION
*
- * Return the MAC of the payload. The caller must already know the
+ * Return the MAC of the payload. The caller must already know the
* length of the MAC. The caller must not free the MAC.
*
***/
*
* DESCRIPTION
*
- * Return the IV of the payload. The caller must already know the
+ * Return the IV of the payload. The caller must already know the
* length of the IV. The caller must not free the IV.
*
***/
* is used to produce the signature. This function returns the encoded
* payload with the signature or NULL on error. Caller must free the
* returned buffer. The `hash' SHOULD be SHA-1 hash function.
- *
+ *
* Application usually does not need to call this since the function
* silc_message_payload_encode calls this automatically if the caller
* wants to sign the message.
*
* SilcPublicKey
* silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
- * unsigned char **pk_data,
+ * const unsigned char **pk_data,
* SilcUInt32 *pk_data_len);
*
* DESCRIPTION
***/
SilcPublicKey
silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
- unsigned char **pk_data,
+ const unsigned char **pk_data,
SilcUInt32 *pk_data_len);
#endif /* SILCMESSAGE_H */
* DESCRIPTION
*
* The SILC secure binary packet protocol interface, provides interface for
- * sending and receiving SILC packets. The interface provides a packet engine,
- * that can be used to receive packets from packet streams, and routines
- * for sending all kinds of SILC packets.
+ * sending and receiving SILC packets. The interface provides a packet
+ * engine, that can be used to receive packets from packet streams, and
+ * routines for sending all kinds of SILC packets.
*
* The packet engine and packet stream are thread safe. They can be safely
* used in multi threaded environment.
noinst_LTLIBRARIES = libsilccrypt.la
libsilccrypt_la_SOURCES = \
- none.c \
- rc5.c \
- md5.c \
- aes.c \
- rsa.c \
- sha1.c \
- sha256.c \
- twofish.c \
- blowfish.c \
- cast.c \
- silccipher.c \
- silchash.c \
- silchmac.c \
- silcrng.c \
- silcpkcs.c \
- silcpkcs1.c
+ none.c \
+ rc5.c \
+ md5.c \
+ aes.c \
+ rsa.c \
+ sha1.c \
+ sha256.c \
+ twofish.c \
+ blowfish.c \
+ cast.c \
+ silccipher.c \
+ silchash.c \
+ silchmac.c \
+ silcrng.c \
+ silcpkcs.c \
+ silcpkcs1.c \
+ silcpk.c
if SILC_LIBTOOLFIX
# Tell libtool to compile silccrypt as shared since silcsim will need it.
silcpkcs.h \
silcrng.h \
silcpkcs1.h \
- twofish.h
+ twofish.h \
+ silcpk.h
SILC_EXTRA_DIST = tests
#endif SILC_DIST_TOOLKIT
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2006 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Fixed double free in public key setting. Use a bit larger e as
starting point in key generation.
+ o Fri Dec 30 13:39:51 EET 2005 Pekka
+
+ Support PKCS #1 format public and private keys. Support for new
+ PKCS API.
*/
#include "silc.h"
-#include "rsa_internal.h"
#include "rsa.h"
-/*
- * SILC PKCS API for RSA
- */
-
-/* Generates RSA key pair. */
-
-SILC_PKCS_API_INIT(rsa)
-{
- SilcUInt32 prime_bits = keylen / 2;
- SilcMPInt p, q;
- SilcBool found = FALSE;
-
- if (keylen < 768 || keylen > 16384)
- return FALSE;
-
- printf("Generating RSA Public and Private keys, might take a while...\n");
-
- silc_mp_init(&p);
- silc_mp_init(&q);
-
- /* Find p and q */
- while (!found) {
- printf("Finding p: ");
- silc_math_gen_prime(&p, prime_bits, TRUE, rng);
-
- printf("\nFinding q: ");
- silc_math_gen_prime(&q, prime_bits, TRUE, rng);
-
- if ((silc_mp_cmp(&p, &q)) == 0)
- printf("\nFound equal primes, not good, retrying...\n");
- else
- found = TRUE;
- }
-
- /* If p is smaller than q, switch them */
- if ((silc_mp_cmp(&p, &q)) > 0) {
- SilcMPInt hlp;
- silc_mp_init(&hlp);
-
- silc_mp_set(&hlp, &p);
- silc_mp_set(&p, &q);
- silc_mp_set(&q, &hlp);
-
- silc_mp_uninit(&hlp);
- }
-
- /* Generate the actual keys */
- rsa_generate_keys((RsaKey *)context, keylen, &p, &q);
-
- silc_mp_uninit(&p);
- silc_mp_uninit(&q);
-
- printf("\nKeys generated successfully.\n");
-
- return TRUE;
-}
-
-SILC_PKCS_API_CLEAR_KEYS(rsa)
-{
- rsa_clear_keys((RsaKey *)context);
-}
-
-/* Returns SILC style encoded RSA public key. */
-
-SILC_PKCS_API_GET_PUBLIC_KEY(rsa)
-{
- RsaKey *key = (RsaKey *)context;
- unsigned char *e, *n, *ret;
- SilcUInt32 e_len, n_len;
- unsigned char tmp[4];
-
- e = silc_mp_mp2bin(&key->e, 0, &e_len);
- n = silc_mp_mp2bin(&key->n, (key->bits + 7) / 8, &n_len);
-
- *ret_len = e_len + 4 + n_len + 4;
- ret = silc_calloc(*ret_len, sizeof(unsigned char));
-
- /* Put the length of the e. */
- SILC_PUT32_MSB(e_len, tmp);
- memcpy(ret, tmp, 4);
-
- /* Put the e. */
- memcpy(ret + 4, e, e_len);
-
- /* Put the length of the n. */
- SILC_PUT32_MSB(n_len, tmp);
- memcpy(ret + 4 + e_len, tmp, 4);
-
- /* Put the n. */
- memcpy(ret + 4 + e_len + 4, n, n_len);
-
- memset(e, 0, e_len);
- memset(n, 0, n_len);
- silc_free(e);
- silc_free(n);
-
- return ret;
-}
-
-/* Returns SILC style encoded RSA private key. Public key is always
- returned in private key as well. Public keys are often derived
- directly from private key. */
-
-SILC_PKCS_API_GET_PRIVATE_KEY(rsa)
-{
- RsaKey *key = (RsaKey *)context;
- SilcBuffer buf;
- unsigned char *e, *n, *d, *ret, *dp = NULL, *dq = NULL;
- unsigned char *pq = NULL, *qp = NULL, *p = NULL, *q = NULL;
- SilcUInt32 e_len, n_len, d_len, dp_len, dq_len, pq_len, qp_len, p_len, q_len;
- SilcUInt32 len = 0;
-
- e = silc_mp_mp2bin(&key->e, 0, &e_len);
- n = silc_mp_mp2bin(&key->n, (key->bits + 7) / 8, &n_len);
- d = silc_mp_mp2bin(&key->d, 0, &d_len);
- if (key->crt) {
- dp = silc_mp_mp2bin(&key->dP, 0, &dp_len);
- dq = silc_mp_mp2bin(&key->dQ, 0, &dq_len);
- pq = silc_mp_mp2bin(&key->pQ, 0, &pq_len);
- qp = silc_mp_mp2bin(&key->qP, 0, &qp_len);
- p = silc_mp_mp2bin(&key->p, 0, &p_len);
- q = silc_mp_mp2bin(&key->q, 0, &q_len);
- len = dp_len + 4 + dq_len + 4 + pq_len + 4 + qp_len + 4 + p_len + 4 +
- q_len + 4;
- }
-
- buf = silc_buffer_alloc_size(e_len + 4 + n_len + 4 + d_len + 4 + len);
- len = silc_buffer_format(buf,
- SILC_STR_UI_INT(e_len),
- SILC_STR_UI_XNSTRING(e, e_len),
- SILC_STR_UI_INT(n_len),
- SILC_STR_UI_XNSTRING(n, n_len),
- SILC_STR_UI_INT(d_len),
- SILC_STR_UI_XNSTRING(d, d_len),
- SILC_STR_END);
-
- if (key->crt) {
- silc_buffer_pull(buf, len);
- silc_buffer_format(buf,
- SILC_STR_UI_INT(dp_len),
- SILC_STR_UI_XNSTRING(dp, dp_len),
- SILC_STR_UI_INT(dq_len),
- SILC_STR_UI_XNSTRING(dq, dq_len),
- SILC_STR_UI_INT(pq_len),
- SILC_STR_UI_XNSTRING(pq, pq_len),
- SILC_STR_UI_INT(qp_len),
- SILC_STR_UI_XNSTRING(qp, qp_len),
- SILC_STR_UI_INT(p_len),
- SILC_STR_UI_XNSTRING(p, p_len),
- SILC_STR_UI_INT(q_len),
- SILC_STR_UI_XNSTRING(q, q_len),
- SILC_STR_END);
- silc_buffer_push(buf, len);
-
- memset(dp, 0, dp_len);
- memset(dq, 0, dq_len);
- memset(pq, 0, pq_len);
- memset(qp, 0, qp_len);
- memset(p, 0, p_len);
- memset(q, 0, q_len);
- silc_free(dp);
- silc_free(dq);
- silc_free(pq);
- silc_free(qp);
- silc_free(p);
- silc_free(q);
- }
-
- memset(d, 0, d_len);
- silc_free(e);
- silc_free(n);
- silc_free(d);
-
- ret = silc_buffer_steal(buf, ret_len);
- silc_buffer_free(buf);
- return ret;
-}
-
-/* Set public key */
-
-SILC_PKCS_API_SET_PUBLIC_KEY(rsa)
-{
- RsaKey *key = (RsaKey *)context;
- unsigned char tmp[4];
- SilcUInt32 e_len, n_len;
-
- if (key->pub_set) {
- silc_mp_uninit(&key->e);
- silc_mp_uninit(&key->n);
- key->pub_set = FALSE;
- }
-
- if (key_len < 4)
- return 0;
-
- silc_mp_init(&key->e);
- silc_mp_init(&key->n);
-
- memcpy(tmp, key_data, 4);
- SILC_GET32_MSB(e_len, tmp);
- if (!e_len || e_len + 4 > key_len) {
- silc_mp_uninit(&key->e);
- silc_mp_uninit(&key->n);
- return 0;
- }
-
- silc_mp_bin2mp(key_data + 4, e_len, &key->e);
-
- if (key_len < 4 + e_len + 4) {
- silc_mp_uninit(&key->e);
- silc_mp_uninit(&key->n);
- return 0;
- }
-
- memcpy(tmp, key_data + 4 + e_len, 4);
- SILC_GET32_MSB(n_len, tmp);
- if (!n_len || e_len + 4 + n_len + 4 > key_len) {
- silc_mp_uninit(&key->e);
- silc_mp_uninit(&key->n);
- return 0;
- }
-
- silc_mp_bin2mp(key_data + 4 + e_len + 4, n_len, &key->n);
-
- key->bits = silc_mp_sizeinbase(&key->n, 2);
- key->pub_set = TRUE;
-
- return key->bits;
-}
-
-/* Set private key. This derives the public key from the private
- key and sets the public key as well. Public key should not be set
- already and should not be set after setting private key. */
-
-SILC_PKCS_API_SET_PRIVATE_KEY(rsa)
-{
- RsaKey *key = (RsaKey *)context;
- SilcBufferStruct k;
- unsigned char *tmp;
- SilcUInt32 len;
-
- if (key->prv_set) {
- silc_mp_uninit(&key->d);
- key->prv_set = FALSE;
- }
-
- if (key->pub_set) {
- silc_mp_uninit(&key->e);
- silc_mp_uninit(&key->n);
- key->pub_set = FALSE;
- }
-
- if (key_len < 4)
- return FALSE;
-
- silc_buffer_set(&k, key_data, key_len);
-
- silc_mp_init(&key->e);
- silc_mp_init(&key->n);
- silc_mp_init(&key->d);
- key->prv_set = TRUE;
- key->pub_set = TRUE;
-
- /* Get e */
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_INT(&len),
- SILC_STR_END) < 0)
- goto err;
- silc_buffer_pull(&k, 4);
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_XNSTRING(&tmp, len),
- SILC_STR_END) < 0)
- goto err;
- silc_mp_bin2mp(tmp, len, &key->e);
- silc_buffer_pull(&k, len);
-
- /* Get n */
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_INT(&len),
- SILC_STR_END) < 0)
- goto err;
- silc_buffer_pull(&k, 4);
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_XNSTRING(&tmp, len),
- SILC_STR_END) < 0)
- goto err;
- silc_mp_bin2mp(tmp, len, &key->n);
- silc_buffer_pull(&k, len);
-
- /* Get d */
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_INT(&len),
- SILC_STR_END) < 0)
- goto err;
- silc_buffer_pull(&k, 4);
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_XNSTRING(&tmp, len),
- SILC_STR_END) < 0)
- goto err;
- silc_mp_bin2mp(tmp, len, &key->d);
- silc_buffer_pull(&k, len);
-
- /* Get optimized d for CRT, if present. */
- if (silc_buffer_len(&k) > 4) {
- key->crt = TRUE;
- silc_mp_init(&key->dP);
- silc_mp_init(&key->dQ);
- silc_mp_init(&key->pQ);
- silc_mp_init(&key->qP);
- silc_mp_init(&key->p);
- silc_mp_init(&key->q);
-
- /* Get dP */
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_INT(&len),
- SILC_STR_END) < 0)
- goto err;
- silc_buffer_pull(&k, 4);
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_XNSTRING(&tmp, len),
- SILC_STR_END) < 0)
- goto err;
- silc_mp_bin2mp(tmp, len, &key->dP);
- silc_buffer_pull(&k, len);
-
- /* Get dQ */
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_INT(&len),
- SILC_STR_END) < 0)
- goto err;
- silc_buffer_pull(&k, 4);
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_XNSTRING(&tmp, len),
- SILC_STR_END) < 0)
- goto err;
- silc_mp_bin2mp(tmp, len, &key->dQ);
- silc_buffer_pull(&k, len);
-
- /* Get pQ */
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_INT(&len),
- SILC_STR_END) < 0)
- goto err;
- silc_buffer_pull(&k, 4);
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_XNSTRING(&tmp, len),
- SILC_STR_END) < 0)
- goto err;
- silc_mp_bin2mp(tmp, len, &key->pQ);
- silc_buffer_pull(&k, len);
-
- /* Get qP */
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_INT(&len),
- SILC_STR_END) < 0)
- goto err;
- silc_buffer_pull(&k, 4);
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_XNSTRING(&tmp, len),
- SILC_STR_END) < 0)
- goto err;
- silc_mp_bin2mp(tmp, len, &key->qP);
- silc_buffer_pull(&k, len);
-
- /* Get p */
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_INT(&len),
- SILC_STR_END) < 0)
- goto err;
- silc_buffer_pull(&k, 4);
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_XNSTRING(&tmp, len),
- SILC_STR_END) < 0)
- goto err;
- silc_mp_bin2mp(tmp, len, &key->p);
- silc_buffer_pull(&k, len);
-
- /* Get q */
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_INT(&len),
- SILC_STR_END) < 0)
- goto err;
- silc_buffer_pull(&k, 4);
- if (silc_buffer_unformat(&k,
- SILC_STR_UI_XNSTRING(&tmp, len),
- SILC_STR_END) < 0)
- goto err;
- silc_mp_bin2mp(tmp, len, &key->q);
- silc_buffer_pull(&k, len);
- }
-
- key->bits = silc_mp_sizeinbase(&key->n, 2);
- return key->bits;
-
- err:
- rsa_clear_keys(key);
- return FALSE;
-}
-
-SILC_PKCS_API_CONTEXT_LEN(rsa)
-{
- return sizeof(RsaKey);
-}
-
-/* Raw RSA routines */
-
-SILC_PKCS_API_ENCRYPT(rsa)
-{
- RsaKey *key = (RsaKey *)context;
- int tmplen;
- SilcMPInt mp_tmp;
- SilcMPInt mp_dst;
-
- silc_mp_init(&mp_tmp);
- silc_mp_init(&mp_dst);
-
- /* Format the data into MP int */
- silc_mp_bin2mp(src, src_len, &mp_tmp);
-
- /* Encrypt */
- rsa_public_operation(key, &mp_tmp, &mp_dst);
-
- tmplen = (key->bits + 7) / 8;
-
- /* Format the MP int back into data */
- silc_mp_mp2bin_noalloc(&mp_dst, dst, tmplen);
- *dst_len = tmplen;
-
- silc_mp_uninit(&mp_tmp);
- silc_mp_uninit(&mp_dst);
-
- return TRUE;
-}
-
-SILC_PKCS_API_DECRYPT(rsa)
-{
- RsaKey *key = (RsaKey *)context;
- int tmplen;
- SilcMPInt mp_tmp;
- SilcMPInt mp_dst;
-
- silc_mp_init(&mp_tmp);
- silc_mp_init(&mp_dst);
-
- /* Format the data into MP int */
- silc_mp_bin2mp(src, src_len, &mp_tmp);
-
- /* Decrypt */
- rsa_private_operation(key, &mp_tmp, &mp_dst);
-
- tmplen = (key->bits + 7) / 8;
-
- /* Format the MP int back into data */
- silc_mp_mp2bin_noalloc(&mp_dst, dst, tmplen);
- *dst_len = tmplen;
-
- silc_mp_uninit(&mp_tmp);
- silc_mp_uninit(&mp_dst);
-
- return TRUE;
-}
-
-SILC_PKCS_API_SIGN(rsa)
-{
- RsaKey *key = (RsaKey *)context;
- int tmplen;
- SilcMPInt mp_tmp;
- SilcMPInt mp_dst;
-
- silc_mp_init(&mp_tmp);
- silc_mp_init(&mp_dst);
-
- /* Format the data into MP int */
- silc_mp_bin2mp(src, src_len, &mp_tmp);
-
- /* Sign */
- rsa_private_operation(key, &mp_tmp, &mp_dst);
-
- tmplen = (key->bits + 7) / 8;
-
- /* Format the MP int back into data */
- silc_mp_mp2bin_noalloc(&mp_dst, dst, tmplen);
- *dst_len = tmplen;
-
- silc_mp_uninit(&mp_tmp);
- silc_mp_uninit(&mp_dst);
-
- return TRUE;
-}
-
-SILC_PKCS_API_VERIFY(rsa)
-{
- RsaKey *key = (RsaKey *)context;
- int ret;
- SilcMPInt mp_tmp, mp_tmp2;
- SilcMPInt mp_dst;
-
- silc_mp_init(&mp_tmp);
- silc_mp_init(&mp_tmp2);
- silc_mp_init(&mp_dst);
-
- /* Format the signature into MP int */
- silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
-
- /* Verify */
- rsa_public_operation(key, &mp_tmp2, &mp_dst);
-
- /* Format the data into MP int */
- silc_mp_bin2mp(data, data_len, &mp_tmp);
-
- ret = TRUE;
-
- /* Compare */
- if ((silc_mp_cmp(&mp_tmp, &mp_dst)) != 0)
- ret = FALSE;
-
- silc_mp_uninit(&mp_tmp);
- silc_mp_uninit(&mp_tmp2);
- silc_mp_uninit(&mp_dst);
-
- return ret;
-}
-
-
-/* PKCS#1 RSA routines */
-
-SILC_PKCS_API_ENCRYPT(pkcs1)
-{
- RsaKey *key = (RsaKey *)context;
- SilcMPInt mp_tmp;
- SilcMPInt mp_dst;
- unsigned char padded[2048 + 1];
- SilcUInt32 len = (key->bits + 7) / 8;
-
- if (sizeof(padded) < len)
- return FALSE;
-
- /* Pad data */
- if (!silc_pkcs1_encode(SILC_PKCS1_BT_PUB, src, src_len,
- padded, len, NULL))
- return FALSE;
-
- silc_mp_init(&mp_tmp);
- silc_mp_init(&mp_dst);
-
- /* Data to MP */
- silc_mp_bin2mp(padded, len, &mp_tmp);
-
- /* Encrypt */
- rsa_public_operation(key, &mp_tmp, &mp_dst);
-
- /* MP to data */
- silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
- *dst_len = len;
-
- memset(padded, 0, sizeof(padded));
- silc_mp_uninit(&mp_tmp);
- silc_mp_uninit(&mp_dst);
-
- return TRUE;
-}
-
-SILC_PKCS_API_DECRYPT(pkcs1)
-{
- RsaKey *key = (RsaKey *)context;
- SilcMPInt mp_tmp;
- SilcMPInt mp_dst;
- unsigned char *padded, unpadded[2048 + 1];
- SilcUInt32 padded_len;
-
- silc_mp_init(&mp_tmp);
- silc_mp_init(&mp_dst);
-
- /* Data to MP */
- silc_mp_bin2mp(src, src_len, &mp_tmp);
-
- /* Decrypt */
- rsa_private_operation(key, &mp_tmp, &mp_dst);
-
- /* MP to data */
- padded = silc_mp_mp2bin(&mp_dst, (key->bits + 7) / 8, &padded_len);
-
- /* Unpad data */
- if (!silc_pkcs1_decode(SILC_PKCS1_BT_PUB, padded, padded_len,
- unpadded, sizeof(unpadded), dst_len)) {
- memset(padded, 0, padded_len);
- silc_free(padded);
- silc_mp_uninit(&mp_tmp);
- silc_mp_uninit(&mp_dst);
- return FALSE;
- }
-
- /* Copy to destination */
- memcpy(dst, unpadded, *dst_len);
-
- memset(padded, 0, padded_len);
- memset(unpadded, 0, sizeof(unpadded));
- silc_free(padded);
- silc_mp_uninit(&mp_tmp);
- silc_mp_uninit(&mp_dst);
-
- return TRUE;
-}
-
-SILC_PKCS_API_SIGN(pkcs1)
-{
- RsaKey *key = (RsaKey *)context;
- SilcMPInt mp_tmp;
- SilcMPInt mp_dst;
- unsigned char padded[2048 + 1];
- SilcUInt32 len = (key->bits + 7) / 8;
-
- if (sizeof(padded) < len)
- return FALSE;
-
- /* Pad data */
- if (!silc_pkcs1_encode(SILC_PKCS1_BT_PRV1, src, src_len,
- padded, len, NULL))
- return FALSE;
-
- silc_mp_init(&mp_tmp);
- silc_mp_init(&mp_dst);
-
- /* Data to MP */
- silc_mp_bin2mp(padded, len, &mp_tmp);
-
- /* Sign */
- rsa_private_operation(key, &mp_tmp, &mp_dst);
-
- /* MP to data */
- silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
- *dst_len = len;
-
- memset(padded, 0, sizeof(padded));
- silc_mp_uninit(&mp_tmp);
- silc_mp_uninit(&mp_dst);
-
- return TRUE;
-}
-
-SILC_PKCS_API_VERIFY(pkcs1)
-{
- RsaKey *key = (RsaKey *)context;
- int ret = TRUE;
- SilcMPInt mp_tmp2;
- SilcMPInt mp_dst;
- unsigned char *verify, unpadded[2048 + 1];
- SilcUInt32 verify_len, len = (key->bits + 7) / 8;
-
- silc_mp_init(&mp_tmp2);
- silc_mp_init(&mp_dst);
-
- /* Format the signature into MP int */
- silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
-
- /* Verify */
- rsa_public_operation(key, &mp_tmp2, &mp_dst);
-
- /* MP to data */
- verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);
-
- /* Unpad data */
- if (!silc_pkcs1_decode(SILC_PKCS1_BT_PRV1, verify, verify_len,
- unpadded, sizeof(unpadded), &len)) {
- memset(verify, 0, verify_len);
- silc_free(verify);
- silc_mp_uninit(&mp_tmp2);
- silc_mp_uninit(&mp_dst);
- return FALSE;
- }
-
- /* Compare */
- if (memcmp(data, unpadded, len))
- ret = FALSE;
-
- memset(verify, 0, verify_len);
- memset(unpadded, 0, sizeof(unpadded));
- silc_free(verify);
- silc_mp_uninit(&mp_tmp2);
- silc_mp_uninit(&mp_dst);
-
- return ret;
-}
-
/* Generates RSA public and private keys. Primes p and q that are used
to compute the modulus n has to be generated before calling this. They
are then sent as argument for the function. */
-SilcBool rsa_generate_keys(RsaKey *key, SilcUInt32 bits,
- SilcMPInt *p, SilcMPInt *q)
+SilcBool rsa_generate_keys(SilcUInt32 bits, SilcMPInt *p, SilcMPInt *q,
+ void **ret_public_key, void **ret_private_key)
{
+ RsaPublicKey *pubkey;
+ RsaPrivateKey *privkey;
SilcMPInt phi, hlp;
SilcMPInt div, lcm;
SilcMPInt pm1, qm1;
+ *ret_public_key = pubkey = silc_calloc(1, sizeof(*pubkey));
+ if (!pubkey)
+ return FALSE;
+
+ *ret_private_key = privkey = silc_calloc(1, sizeof(*privkey));
+ if (!privkey)
+ return FALSE;
+
/* Initialize variables */
- silc_mp_init(&key->n);
- silc_mp_init(&key->e);
- silc_mp_init(&key->d);
- silc_mp_init(&key->dP);
- silc_mp_init(&key->dQ);
- silc_mp_init(&key->pQ);
- silc_mp_init(&key->qP);
+ silc_mp_init(&privkey->n);
+ silc_mp_init(&privkey->e);
+ silc_mp_init(&privkey->d);
+ silc_mp_init(&privkey->dP);
+ silc_mp_init(&privkey->dQ);
+ silc_mp_init(&privkey->qP);
silc_mp_init(&phi);
silc_mp_init(&hlp);
silc_mp_init(&div);
silc_mp_init(&qm1);
/* Set modulus length */
- key->bits = bits;
+ privkey->bits = bits;
/* Compute modulus, n = p * q */
- silc_mp_mul(&key->n, p, q);
+ silc_mp_mul(&privkey->n, p, q);
/* phi = (p - 1) * (q - 1) */
silc_mp_sub_ui(&pm1, p, 1);
/* Set e, the public exponent. We try to use same public exponent
for all keys. Also, to make encryption faster we use small
number. */
- silc_mp_set_ui(&key->e, 65533);
+ silc_mp_set_ui(&privkey->e, 65533);
retry_e:
/* See if e is relatively prime to phi. gcd == greates common divisor,
if gcd equals 1 they are relatively prime. */
- silc_mp_gcd(&hlp, &key->e, &phi);
+ silc_mp_gcd(&hlp, &privkey->e, &phi);
if ((silc_mp_cmp_ui(&hlp, 1)) > 0) {
- silc_mp_add_ui(&key->e, &key->e, 2);
+ silc_mp_add_ui(&privkey->e, &privkey->e, 2);
goto retry_e;
}
/* Find d, the private exponent, e ^ -1 mod lcm(phi). */
silc_mp_gcd(&div, &pm1, &qm1);
silc_mp_div(&lcm, &phi, &div);
- silc_mp_modinv(&key->d, &key->e, &lcm);
-
- /* Optimize d with CRT. We precompute as much as possible. */
- silc_mp_mod(&key->dP, &key->d, &pm1);
- silc_mp_mod(&key->dQ, &key->d, &qm1);
- silc_mp_modinv(&key->pQ, p, q);
- silc_mp_mul(&key->pQ, p, &key->pQ);
- silc_mp_mod(&key->pQ, &key->pQ, &key->n);
- silc_mp_modinv(&key->qP, q, p);
- silc_mp_mul(&key->qP, q, &key->qP);
- silc_mp_mod(&key->qP, &key->qP, &key->n);
- silc_mp_set(&key->p, p);
- silc_mp_set(&key->q, q);
- key->crt = TRUE;
+ silc_mp_modinv(&privkey->d, &privkey->e, &lcm);
+
+ /* Optimize d with CRT. */
+ silc_mp_mod(&privkey->dP, &privkey->d, &pm1);
+ silc_mp_mod(&privkey->dQ, &privkey->d, &qm1);
+ silc_mp_modinv(&privkey->qP, q, p);
+ silc_mp_set(&privkey->p, p);
+ silc_mp_set(&privkey->q, q);
silc_mp_uninit(&phi);
silc_mp_uninit(&hlp);
silc_mp_uninit(&pm1);
silc_mp_uninit(&qm1);
- return TRUE;
-}
+ /* Set public key */
+ silc_mp_init(&pubkey->n);
+ silc_mp_init(&pubkey->e);
+ pubkey->bits = privkey->bits;
+ silc_mp_set(&pubkey->n, &privkey->n);
+ silc_mp_set(&pubkey->e, &privkey->e);
-/* Clears whole key structure. */
-
-SilcBool rsa_clear_keys(RsaKey *key)
-{
- key->bits = 0;
- if (key->pub_set) {
- silc_mp_uninit(&key->n);
- silc_mp_uninit(&key->e);
- }
- if (key->prv_set)
- silc_mp_uninit(&key->d);
- if (key->prv_set && key->crt) {
- silc_mp_uninit(&key->dP);
- silc_mp_uninit(&key->dQ);
- silc_mp_uninit(&key->pQ);
- silc_mp_uninit(&key->qP);
- silc_mp_uninit(&key->p);
- silc_mp_uninit(&key->q);
- }
return TRUE;
}
/* RSA public key operation */
-SilcBool rsa_public_operation(RsaKey *key, SilcMPInt *src, SilcMPInt *dst)
+SilcBool rsa_public_operation(RsaPublicKey *key, SilcMPInt *src,
+ SilcMPInt *dst)
{
/* dst = src ^ e mod n */
silc_mp_pow_mod(dst, src, &key->e, &key->n);
/* RSA private key operation */
-SilcBool rsa_private_operation(RsaKey *key, SilcMPInt *src, SilcMPInt *dst)
+SilcBool rsa_private_operation(RsaPrivateKey *key, SilcMPInt *src,
+ SilcMPInt *dst)
{
- if (!key->crt) {
- /* dst = src ^ d mod n */
- silc_mp_pow_mod(dst, src, &key->d, &key->n);
- } else {
- /* CRT */
- SilcMPInt tmp;
-
- silc_mp_init(&tmp);
-
- /* dst = ((src ^ dP mod p) * qP) + ((src ^ dQ mod q) * pQ) mod n */
- silc_mp_pow_mod(dst, src, &key->dP, &key->p);
- silc_mp_mul(dst, dst, &key->qP);
- silc_mp_pow_mod(&tmp, src, &key->dQ, &key->q);
- silc_mp_mul(&tmp, &tmp, &key->pQ);
- silc_mp_add(dst, dst, &tmp);
- silc_mp_mod(dst, dst, &key->n);
-
- silc_mp_uninit(&tmp);
- }
+ SilcMPInt tmp;
+
+ silc_mp_init(&tmp);
+
+ /* dst = (src ^ dP mod p) */
+ silc_mp_pow_mod(dst, src, &key->dP, &key->p);
+
+ /* tmp = (src ^ dQ mod q) */
+ silc_mp_pow_mod(&tmp, src, &key->dQ, &key->q);
+
+ /* dst = (dst - tmp) * qP mod p */
+ silc_mp_sub(dst, dst, &tmp);
+ silc_mp_mul(dst, dst, &key->qP);
+ silc_mp_mod(dst, dst, &key->p);
+
+ /* dst = (q * dst) + tmp */
+ silc_mp_mul(dst, dst, &key->q);
+ silc_mp_add(dst, dst, &tmp);
+
+ silc_mp_uninit(&tmp);
return TRUE;
}
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2003 Pekka Riikonen
+ Copyright (C) 1997 - 2006 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#ifndef RSA_H
#define RSA_H
-/*
- * SILC PKCS API for RSA
- */
-
-SILC_PKCS_API_INIT(rsa);
-SILC_PKCS_API_CLEAR_KEYS(rsa);
-SILC_PKCS_API_GET_PUBLIC_KEY(rsa);
-SILC_PKCS_API_GET_PRIVATE_KEY(rsa);
-SILC_PKCS_API_SET_PUBLIC_KEY(rsa);
-SILC_PKCS_API_SET_PRIVATE_KEY(rsa);
-SILC_PKCS_API_CONTEXT_LEN(rsa);
-SILC_PKCS_API_ENCRYPT(rsa);
-SILC_PKCS_API_DECRYPT(rsa);
-SILC_PKCS_API_SIGN(rsa);
-SILC_PKCS_API_VERIFY(rsa);
-
-SILC_PKCS_API_ENCRYPT(pkcs1);
-SILC_PKCS_API_DECRYPT(pkcs1);
-SILC_PKCS_API_SIGN(pkcs1);
-SILC_PKCS_API_VERIFY(pkcs1);
-
-
-#endif
+/* RSA Public Key */
+typedef struct {
+ int bits; /* bits in key */
+ SilcMPInt n; /* modulus */
+ SilcMPInt e; /* public exponent */
+} RsaPublicKey;
+
+/* RSA Private Key */
+typedef struct {
+ int bits; /* bits in key */
+ SilcMPInt n; /* modulus */
+ SilcMPInt e; /* public exponent */
+ SilcMPInt d; /* private exponent */
+ SilcMPInt p; /* CRT, p */
+ SilcMPInt q; /* CRT, q */
+ SilcMPInt dP; /* CRT, d mod p - 1 */
+ SilcMPInt dQ; /* CRT, d mod q - 1 */
+ SilcMPInt qP; /* CRT, q ^ -1 mod p */
+} RsaPrivateKey;
+
+SilcBool rsa_generate_keys(SilcUInt32 bits, SilcMPInt *p, SilcMPInt *q,
+ void **ret_public_key, void **ret_private_key);
+SilcBool rsa_public_operation(RsaPublicKey *key, SilcMPInt *src,
+ SilcMPInt *dst);
+SilcBool rsa_private_operation(RsaPrivateKey *key, SilcMPInt *src,
+ SilcMPInt *dst);
+
+#endif /* RSA_H */
+++ /dev/null
-/*
-
- rsa_internal.h
-
- Author: Pekka Riikonen <priikone@silcnet.org>
-
- Copyright (C) 1997 - 2003 Pekka Riikonen
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
-*/
-
-#ifndef RSA_INTERNAL_H
-#define RSA_INTERNAL_H
-
-/* RSA Keys, includes both Private and Public key */
-typedef struct {
- int bits; /* bits in key */
- SilcMPInt n; /* modulus */
- SilcMPInt e; /* public exponent */
- SilcMPInt d; /* private exponent (no CRT) */
- SilcMPInt p; /* p */
- SilcMPInt q; /* q */
- SilcMPInt dP; /* CRT, d mod p - 1 */
- SilcMPInt dQ; /* CRT, d mod q - 1 */
- SilcMPInt pQ; /* CRT, p * (p ^ -1 mod q) mod n */
- SilcMPInt qP; /* CRT, q * (q ^ -1 mod p) mod n */
- unsigned int pub_set : 1; /* TRUE if n and e is set */
- unsigned int prv_set : 1; /* TRUE if d is set */
- unsigned int crt : 1; /* TRUE if CRT is used */
-} RsaKey;
-
-SilcBool rsa_generate_keys(RsaKey *key, SilcUInt32 bits,
- SilcMPInt *p, SilcMPInt *q);
-SilcBool rsa_clear_keys(RsaKey *key);
-SilcBool rsa_public_operation(RsaKey *key, SilcMPInt *src, SilcMPInt *dst);
-SilcBool rsa_private_operation(RsaKey *key, SilcMPInt *src, SilcMPInt *dst);
-
-#endif
/*
- silchash.h
+ silchash.h
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2002 Pekka Riikonen
+ Copyright (C) 1997 - 2005 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/****s* silccrypt/SilcHashAPI/SilcHash
*
* NAME
- *
+ *
* typedef struct SilcHashStruct *SilcHash;
*
* DESCRIPTION
/****s* silccrypt/SilcHashAPI/SilcHashObject
*
* NAME
- *
+ *
* typedef struct { ... } SilcHashObject;
*
* DESCRIPTION
* put them into a buffer and compute the digest from the buffer by
* calling the silc_hash_make, or you can use the silc_hash_init,
* silc_hash_update and silc_hash_final to do the digest. This function
- * prepares the allocated hash function context for this kind of digest
+ * prepares the allocated hash function context for this kind of digest
* computation. To add the data to be used in the digest computation
* call the silc_hash_update function.
*
--- /dev/null
+/*
+
+ silcpk.c
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 1997 - 2006 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#include "silc.h"
+#include "silcpk_i.h"
+
+/****************************** Key generation *******************************/
+
+/* Generate new SILC key pair. */
+
+SilcBool silc_pkcs_silc_generate_key(const char *algorithm,
+ const char *scheme,
+ SilcUInt32 bits_key_len,
+ const char *identifier,
+ SilcRng rng,
+ SilcPublicKey *ret_public_key,
+ SilcPrivateKey *ret_private_key)
+{
+ SilcSILCPublicKey pubkey;
+ SilcSILCPrivateKey privkey;
+ const SilcPKCSAlgorithm *alg;
+ const SilcPKCSObject *pkcs;
+
+ SILC_LOG_DEBUG(("Generating SILC %s key pair with key length %d bits",
+ algorithm, bits_key_len));
+
+ if (!rng)
+ return FALSE;
+
+ pkcs = silc_pkcs_find_pkcs(SILC_PKCS_SILC);
+ if (!pkcs)
+ return FALSE;
+
+ alg = silc_pkcs_find_algorithm(algorithm, scheme);
+ if (!alg)
+ return FALSE;
+
+ /* Allocate SILC public key */
+ pubkey = silc_calloc(1, sizeof(*pubkey));
+ if (!pubkey)
+ return FALSE;
+ pubkey->pkcs = alg;
+
+ /* Decode identifier */
+ if (!silc_pkcs_silc_decode_identifier(identifier, &pubkey->identifier)) {
+ silc_free(pubkey);
+ return FALSE;
+ }
+
+ /* Allocate SILC private key */
+ privkey = silc_calloc(1, sizeof(*privkey));
+ if (!privkey) {
+ silc_free(pubkey);
+ return FALSE;
+ }
+ privkey->pkcs = alg;
+
+ /* Allocate public key */
+ *ret_public_key = silc_calloc(1, sizeof(**ret_public_key));
+ if (!(*ret_public_key)) {
+ silc_free(pubkey);
+ silc_free(privkey);
+ return FALSE;
+ }
+ (*ret_public_key)->pkcs = pkcs;
+ (*ret_public_key)->public_key = pubkey;
+
+ /* Allocate private key */
+ *ret_private_key = silc_calloc(1, sizeof(**ret_private_key));
+ if (!(*ret_private_key)) {
+ silc_free(pubkey);
+ silc_free(privkey);
+ silc_free(*ret_public_key);
+ return FALSE;
+ }
+ (*ret_private_key)->pkcs = pkcs;
+ (*ret_private_key)->private_key = privkey;
+
+ /* Generate the algorithm key pair */
+ if (!alg->generate_key(bits_key_len, rng, &pubkey->public_key,
+ &privkey->private_key)) {
+ silc_free(pubkey);
+ silc_free(privkey);
+ silc_free(*ret_public_key);
+ silc_free(*ret_private_key);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/**************************** Utility functions ******************************/
+
+/* Decodes the provided `identifier' */
+
+SilcBool silc_pkcs_silc_decode_identifier(const char *identifier,
+ SilcPublicKeyIdentifier ident)
+{
+ char *cp, *item;
+ int len;
+
+ /* Protocol says that at least UN and HN must be provided as identifier */
+ if (!strstr(identifier, "UN=") && !strstr(identifier, "HN=")) {
+ SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
+ "identifiers"));
+ return FALSE;
+ }
+
+ cp = (char *)identifier;
+ while (cp) {
+ len = strcspn(cp, ",");
+ if (len < 1) {
+ cp = NULL;
+ break;
+ }
+ if (len - 1 >= 0 && cp[len - 1] == '\\') {
+ while (cp) {
+ if (len + 1 > strlen(cp)) {
+ cp = NULL;
+ break;
+ }
+ cp += len + 1;
+ len = strcspn(cp, ",") + len;
+ if (len < 1) {
+ cp = NULL;
+ break;
+ }
+ if (len - 1 >= 0 && cp[len - 1] != '\\')
+ break;
+ }
+ }
+
+ if (!cp)
+ break;
+
+ item = silc_calloc(len + 1, sizeof(char));
+ if (!item)
+ return FALSE;
+ if (len > strlen(cp))
+ break;
+ memcpy(item, cp, len);
+
+ if (strstr(item, "UN="))
+ ident->username = strdup(item + strcspn(cp, "=") + 1);
+ else if (strstr(item, "HN="))
+ ident->host = strdup(item + strcspn(cp, "=") + 1);
+ else if (strstr(item, "RN="))
+ ident->realname = strdup(item + strcspn(cp, "=") + 1);
+ else if (strstr(item, "E="))
+ ident->email = strdup(item + strcspn(cp, "=") + 1);
+ else if (strstr(item, "O="))
+ ident->org = strdup(item + strcspn(cp, "=") + 1);
+ else if (strstr(item, "C="))
+ ident->country = strdup(item + strcspn(cp, "=") + 1);
+
+ cp += len;
+ if (strlen(cp) < 1)
+ cp = NULL;
+ else
+ cp += 1;
+
+ if (item)
+ silc_free(item);
+ }
+
+ return TRUE;
+}
+
+/* Encodes and returns SILC public key identifier. If some of the
+ arguments is NULL those are not encoded into the identifier string.
+ Protocol says that at least username and host must be provided. */
+
+char *silc_pkcs_silc_encode_identifier(char *username, char *host,
+ char *realname, char *email,
+ char *org, char *country)
+{
+ SilcBuffer buf;
+ char *identifier;
+ SilcUInt32 len, tlen = 0;
+
+ if (!username || !host)
+ return NULL;
+
+ len = (username ? strlen(username) : 0) +
+ (host ? strlen(host) : 0) +
+ (realname ? strlen(realname) : 0) +
+ (email ? strlen(email) : 0) +
+ (org ? strlen(org) : 0) +
+ (country ? strlen(country) : 0);
+
+ if (len < 3)
+ return NULL;
+
+ len += 3 + 5 + 5 + 4 + 4 + 4;
+ buf = silc_buffer_alloc(len);
+ if (!buf)
+ return NULL;
+ silc_buffer_pull_tail(buf, len);
+
+ if (username) {
+ silc_buffer_format(buf,
+ SILC_STR_UI32_STRING("UN="),
+ SILC_STR_UI32_STRING(username),
+ SILC_STR_END);
+ silc_buffer_pull(buf, 3 + strlen(username));
+ tlen = 3 + strlen(username);
+ }
+
+ if (host) {
+ silc_buffer_format(buf,
+ SILC_STR_UI32_STRING(", "),
+ SILC_STR_UI32_STRING("HN="),
+ SILC_STR_UI32_STRING(host),
+ SILC_STR_END);
+ silc_buffer_pull(buf, 5 + strlen(host));
+ tlen += 5 + strlen(host);
+ }
+
+ if (realname) {
+ silc_buffer_format(buf,
+ SILC_STR_UI32_STRING(", "),
+ SILC_STR_UI32_STRING("RN="),
+ SILC_STR_UI32_STRING(realname),
+ SILC_STR_END);
+ silc_buffer_pull(buf, 5 + strlen(realname));
+ tlen += 5 + strlen(realname);
+ }
+
+ if (email) {
+ silc_buffer_format(buf,
+ SILC_STR_UI32_STRING(", "),
+ SILC_STR_UI32_STRING("E="),
+ SILC_STR_UI32_STRING(email),
+ SILC_STR_END);
+ silc_buffer_pull(buf, 4 + strlen(email));
+ tlen += 4 + strlen(email);
+ }
+
+ if (org) {
+ silc_buffer_format(buf,
+ SILC_STR_UI32_STRING(", "),
+ SILC_STR_UI32_STRING("O="),
+ SILC_STR_UI32_STRING(org),
+ SILC_STR_END);
+ silc_buffer_pull(buf, 4 + strlen(org));
+ tlen += 4 + strlen(org);
+ }
+
+ if (country) {
+ silc_buffer_format(buf,
+ SILC_STR_UI32_STRING(", "),
+ SILC_STR_UI32_STRING("C="),
+ SILC_STR_UI32_STRING(country),
+ SILC_STR_END);
+ silc_buffer_pull(buf, 4 + strlen(country));
+ tlen += 4 + strlen(country);
+ }
+
+ silc_buffer_push(buf, buf->data - buf->head);
+ identifier = silc_calloc(tlen + 1, sizeof(*identifier));
+ if (!identifier)
+ return NULL;
+ memcpy(identifier, buf->data, tlen);
+ silc_buffer_free(buf);
+
+ return identifier;
+}
+
+
+/*************************** Public key routines *****************************/
+
+/* Returns PKCS algorithm context */
+
+const SilcPKCSAlgorithm *silc_pkcs_silc_get_algorithm(void *public_key)
+{
+ SilcSILCPublicKey silc_pubkey = public_key;
+ return silc_pubkey->pkcs;
+}
+
+/* Imports SILC protocol style public key from SILC public key file */
+
+SilcBool silc_pkcs_silc_import_public_key_file(unsigned char *filedata,
+ SilcUInt32 filedata_len,
+ SilcPKCSFileEncoding encoding,
+ void **ret_public_key)
+{
+ SilcUInt32 i, len;
+ unsigned char *data = NULL;
+ SilcBool ret;
+
+ SILC_LOG_DEBUG(("Parsing SILC public key file"));
+
+ if (!ret_public_key)
+ return FALSE;
+
+ /* Check start of file and remove header from the data. */
+ len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
+ if (filedata_len < len + strlen(SILC_PKCS_PUBLIC_KEYFILE_END))
+ return FALSE;
+ for (i = 0; i < len; i++) {
+ if (*filedata != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i])
+ return FALSE;
+ filedata++;
+ }
+ filedata_len -= (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
+ strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
+
+ switch (encoding) {
+ case SILC_PKCS_FILE_BIN:
+ break;
+
+ case SILC_PKCS_FILE_BASE64:
+ data = silc_pem_decode(filedata, filedata_len, &filedata_len);
+ if (!data)
+ return FALSE;
+ filedata = data;
+ break;
+ }
+
+ ret = silc_pkcs_silc_import_public_key(filedata, filedata_len,
+ ret_public_key);
+ silc_free(data);
+
+ return ret;
+}
+
+/* Imports SILC protocol style public key */
+
+SilcBool silc_pkcs_silc_import_public_key(unsigned char *key,
+ SilcUInt32 key_len,
+ void **ret_public_key)
+{
+ const SilcPKCSAlgorithm *pkcs;
+ SilcBufferStruct buf, alg_key;
+ SilcSILCPublicKey silc_pubkey = NULL;
+ SilcAsn1 asn1 = NULL;
+ SilcUInt32 totlen, keydata_len;
+ SilcUInt16 pkcs_len, identifier_len;
+ unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
+ int ret;
+
+ SILC_LOG_DEBUG(("Parsing SILC public key"));
+
+ if (!ret_public_key)
+ return FALSE;
+
+ silc_buffer_set(&buf, key, key_len);
+
+ /* Get length */
+ ret = silc_buffer_unformat(&buf,
+ SILC_STR_UI_INT(&totlen),
+ SILC_STR_END);
+ if (ret == -1)
+ goto err;
+
+ if (totlen + 4 != key_len)
+ goto err;
+
+ /* Get algorithm name and identifier */
+ ret =
+ silc_buffer_unformat(&buf,
+ SILC_STR_OFFSET(4),
+ SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
+ SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
+ SILC_STR_END);
+ if (ret == -1)
+ goto err;
+
+ if (pkcs_len < 1 || identifier_len < 3 ||
+ pkcs_len + identifier_len > totlen)
+ goto err;
+
+ /* Get key data */
+ silc_buffer_pull(&buf, 4 + 2 + pkcs_len + 2 + identifier_len);
+ keydata_len = silc_buffer_len(&buf);
+ ret = silc_buffer_unformat(&buf,
+ SILC_STR_UI_XNSTRING(&key_data,
+ keydata_len),
+ SILC_STR_END);
+ if (ret == -1)
+ goto err;
+
+ /* Allocate SILC public key context */
+ silc_pubkey = silc_calloc(1, sizeof(*silc_pubkey));
+ if (!silc_pubkey)
+ goto err;
+
+ /* Decode SILC identifier */
+ if (!silc_pkcs_silc_decode_identifier(ident, &silc_pubkey->identifier))
+ goto err;
+
+ asn1 = silc_asn1_alloc();
+ if (!asn1)
+ goto err;
+
+ if (!strcmp(pkcs_name, "rsa")) {
+ /* Parse the SILC RSA public key */
+ SilcUInt32 e_len, n_len;
+ SilcMPInt n, e;
+
+ /* Get PKCS object */
+ pkcs = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid");
+ if (!pkcs) {
+ SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
+ goto err;
+ }
+ silc_pubkey->pkcs = pkcs;
+
+ if (keydata_len < 4)
+ goto err;
+ SILC_GET32_MSB(e_len, key_data);
+ if (!e_len || e_len + 4 > keydata_len)
+ goto err;
+ silc_mp_init(&e);
+ silc_mp_bin2mp(key_data + 4, e_len, &e);
+ if (keydata_len < 4 + e_len + 4) {
+ silc_mp_uninit(&e);
+ goto err;
+ }
+ SILC_GET32_MSB(n_len, key_data + 4 + e_len);
+ if (!n_len || e_len + 4 + n_len + 4 > keydata_len) {
+ silc_mp_uninit(&e);
+ goto err;
+ }
+ silc_mp_init(&n);
+ silc_mp_bin2mp(key_data + 4 + e_len + 4, n_len, &n);
+
+ /* Encode to PKCS #1 format */
+ memset(&alg_key, 0, sizeof(alg_key));
+ if (!silc_asn1_encode(asn1, &alg_key,
+ SILC_ASN1_SEQUENCE,
+ SILC_ASN1_INT(&n),
+ SILC_ASN1_INT(&e),
+ SILC_ASN1_END, SILC_ASN1_END)) {
+ silc_mp_uninit(&e);
+ silc_mp_uninit(&n);
+ goto err;
+ }
+
+ silc_mp_uninit(&e);
+ silc_mp_uninit(&n);
+
+ } else if (!strcmp(pkcs_name, "dsa")) {
+ SILC_NOT_IMPLEMENTED("DSA SILC Public Key");
+ goto err;
+
+ } else {
+ SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
+ goto err;
+ }
+
+ /* Import PKCS algorithm public key */
+ if (pkcs->import_public_key)
+ if (!pkcs->import_public_key(alg_key.data, silc_buffer_len(&alg_key),
+ &silc_pubkey->public_key))
+ goto err;
+
+ silc_free(pkcs_name);
+ silc_free(ident);
+ silc_asn1_free(asn1);
+
+ *ret_public_key = silc_pubkey;
+
+ return TRUE;
+
+ err:
+ silc_free(pkcs_name);
+ silc_free(ident);
+ silc_free(silc_pubkey);
+ if (asn1)
+ silc_asn1_free(asn1);
+ return FALSE;
+}
+
+/* Exports public key as SILC protocol style public key file */
+
+unsigned char *
+silc_pkcs_silc_export_public_key_file(void *public_key,
+ SilcPKCSFileEncoding encoding,
+ SilcUInt32 *ret_len)
+{
+ SilcBuffer buf;
+ unsigned char *key, *data;
+ SilcUInt32 key_len;
+
+ SILC_LOG_DEBUG(("Encoding SILC public key file"));
+
+ /* Export key */
+ key = silc_pkcs_silc_export_public_key(public_key, &key_len);
+ if (!key)
+ return NULL;
+
+ switch (encoding) {
+ case SILC_PKCS_FILE_BIN:
+ break;
+
+ case SILC_PKCS_FILE_BASE64:
+ data = silc_pem_encode_file(key, key_len);
+ if (!data)
+ return NULL;
+ silc_free(key);
+ key = data;
+ key_len = strlen(data);
+ break;
+ }
+
+ /* Encode SILC public key file */
+ buf = silc_buffer_alloc_size(key_len +
+ (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
+ strlen(SILC_PKCS_PUBLIC_KEYFILE_END)));
+ if (!buf) {
+ silc_free(key);
+ return NULL;
+ }
+
+ if (silc_buffer_format(buf,
+ SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
+ SILC_STR_UI_XNSTRING(key, key_len),
+ SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
+ SILC_STR_END) < 0) {
+ silc_buffer_free(buf);
+ silc_free(key);
+ return NULL;
+ }
+
+ silc_free(key);
+ key = silc_buffer_steal(buf, ret_len);
+ silc_buffer_free(buf);
+
+ return key;
+}
+
+/* Exports public key as SILC protocol style public key */
+
+unsigned char *silc_pkcs_silc_export_public_key(void *public_key,
+ SilcUInt32 *ret_len)
+{
+ SilcSILCPublicKey silc_pubkey = public_key;
+ const SilcPKCSAlgorithm *pkcs = silc_pubkey->pkcs;
+ SilcBufferStruct alg_key;
+ SilcBuffer buf = NULL;
+ SilcAsn1 asn1 = NULL;
+ unsigned char *pk = NULL, *key = NULL, *ret;
+ SilcUInt32 pk_len, key_len, totlen;
+ char *identifier;
+
+ SILC_LOG_DEBUG(("Encoding SILC public key"));
+
+ /* Export PKCS algorithm public key */
+ if (pkcs->export_public_key)
+ pk = pkcs->export_public_key(silc_pubkey->public_key, &pk_len);
+ if (!pk)
+ return NULL;
+ silc_buffer_set(&alg_key, pk, pk_len);
+
+ /* Encode identifier */
+ identifier =
+ silc_pkcs_silc_encode_identifier(silc_pubkey->identifier.username,
+ silc_pubkey->identifier.host,
+ silc_pubkey->identifier.realname,
+ silc_pubkey->identifier.email,
+ silc_pubkey->identifier.org,
+ silc_pubkey->identifier.country);
+ if (!identifier)
+ goto err;
+
+ asn1 = silc_asn1_alloc();
+ if (!asn1)
+ goto err;
+
+ if (!strcmp(pkcs->name, "rsa")) {
+ /* Parse the PKCS #1 public key */
+ SilcMPInt n, e;
+ SilcUInt32 n_len, e_len;
+ unsigned char *nb, *eb;
+
+ memset(&n, 0, sizeof(n));
+ memset(&e, 0, sizeof(e));
+ if (!silc_asn1_decode(asn1, &alg_key,
+ SILC_ASN1_SEQUENCE,
+ SILC_ASN1_INT(&n),
+ SILC_ASN1_INT(&e),
+ SILC_ASN1_END, SILC_ASN1_END))
+ goto err;
+
+ /* Encode to SILC RSA public key */
+ eb = silc_mp_mp2bin(&e, 0, &e_len);
+ if (!eb)
+ goto err;
+ nb = silc_mp_mp2bin(&n, 0, &n_len);
+ if (!nb)
+ goto err;
+ key_len = e_len + 4 + n_len + 4;
+ key = silc_calloc(key_len, sizeof(*key));
+ if (!key)
+ goto err;
+
+ /* Put e length and e */
+ SILC_PUT32_MSB(e_len, key);
+ memcpy(key + 4, eb, e_len);
+
+ /* Put n length and n. */
+ SILC_PUT32_MSB(n_len, key + 4 + e_len);
+ memcpy(key + 4 + e_len + 4, nb, n_len);
+
+ silc_free(nb);
+ silc_free(eb);
+
+ } else if (!strcmp(pkcs->name, "dsa")) {
+ SILC_NOT_IMPLEMENTED("SILC DSA Public Key");
+ goto err;
+
+ } else {
+ SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
+ goto err;
+ }
+
+ /* Encode SILC Public Key */
+ totlen = 2 + strlen(pkcs->name) + 2 + strlen(identifier) + key_len;
+ buf = silc_buffer_alloc_size(totlen + 4);
+ if (!buf)
+ goto err;
+ if (silc_buffer_format(buf,
+ SILC_STR_UI_INT(totlen),
+ SILC_STR_UI_SHORT(strlen(pkcs->name)),
+ SILC_STR_UI32_STRING(pkcs->name),
+ SILC_STR_UI_SHORT(strlen(identifier)),
+ SILC_STR_UI32_STRING(identifier),
+ SILC_STR_UI_XNSTRING(key, key_len),
+ SILC_STR_END) < 0)
+ goto err;
+
+ ret = silc_buffer_steal(buf, ret_len);
+ silc_buffer_free(buf);
+ silc_free(key);
+ silc_free(identifier);
+ silc_asn1_free(asn1);
+
+ return ret;
+
+ err:
+ silc_free(identifier);
+ silc_free(pk);
+ silc_free(key);
+ if (buf)
+ silc_buffer_free(buf);
+ if (asn1)
+ silc_asn1_free(asn1);
+ return NULL;
+}
+
+/* Return key length */
+
+SilcUInt32 silc_pkcs_silc_public_key_bitlen(void *public_key)
+{
+ SilcSILCPublicKey silc_pubkey = public_key;
+ return silc_pubkey->pkcs->public_key_bitlen(silc_pubkey->public_key);
+}
+
+/* Copy public key */
+
+void *silc_pkcs_silc_public_key_copy(void *public_key)
+{
+ SilcSILCPublicKey silc_pubkey = public_key, new_pubkey;
+
+ new_pubkey = silc_calloc(1, sizeof(*new_pubkey));
+ if (!new_pubkey)
+ return NULL;
+ new_pubkey->pkcs = silc_pubkey->pkcs;
+
+ new_pubkey->public_key =
+ silc_pubkey->pkcs->public_key_copy(silc_pubkey->public_key);
+ if (!new_pubkey->public_key) {
+ silc_free(new_pubkey);
+ return NULL;
+ }
+
+ return new_pubkey;
+}
+
+/* Compares public keys */
+
+SilcBool silc_pkcs_silc_public_key_compare(void *key1, void *key2)
+{
+ SilcSILCPublicKey k1 = key1, k2 = key2;
+
+ if (strcmp(k1->pkcs->name, k2->pkcs->name))
+ return FALSE;
+
+ if ((k1->identifier.username && !k2->identifier.username) ||
+ (!k1->identifier.username && k2->identifier.username) ||
+ (k1->identifier.username && k2->identifier.username &&
+ strcmp(k1->identifier.username, k2->identifier.username)))
+ return FALSE;
+
+ if ((k1->identifier.host && !k2->identifier.host) ||
+ (!k1->identifier.host && k2->identifier.host) ||
+ (k1->identifier.host && k2->identifier.host &&
+ strcmp(k1->identifier.host, k2->identifier.host)))
+ return FALSE;
+
+ if ((k1->identifier.realname && !k2->identifier.realname) ||
+ (!k1->identifier.realname && k2->identifier.realname) ||
+ (k1->identifier.realname && k2->identifier.realname &&
+ strcmp(k1->identifier.realname, k2->identifier.realname)))
+ return FALSE;
+
+ if ((k1->identifier.email && !k2->identifier.email) ||
+ (!k1->identifier.email && k2->identifier.email) ||
+ (k1->identifier.email && k2->identifier.email &&
+ strcmp(k1->identifier.email, k2->identifier.email)))
+ return FALSE;
+
+ if ((k1->identifier.org && !k2->identifier.org) ||
+ (!k1->identifier.org && k2->identifier.org) ||
+ (k1->identifier.org && k2->identifier.org &&
+ strcmp(k1->identifier.org, k2->identifier.org)))
+ return FALSE;
+
+ if ((k1->identifier.country && !k2->identifier.country) ||
+ (!k1->identifier.country && k2->identifier.country) ||
+ (k1->identifier.country && k2->identifier.country &&
+ strcmp(k1->identifier.country, k2->identifier.country)))
+ return FALSE;
+
+ return k1->pkcs->public_key_compare(k1->public_key, k2->public_key);
+}
+
+/* Frees public key */
+
+void silc_pkcs_silc_public_key_free(void *public_key)
+{
+ SilcSILCPublicKey silc_pubkey = public_key;
+
+ silc_pubkey->pkcs->public_key_free(silc_pubkey->public_key);
+
+ silc_free(silc_pubkey->identifier.username);
+ silc_free(silc_pubkey->identifier.host);
+ silc_free(silc_pubkey->identifier.realname);
+ silc_free(silc_pubkey->identifier.email);
+ silc_free(silc_pubkey->identifier.org);
+ silc_free(silc_pubkey->identifier.country);
+ silc_free(silc_pubkey);
+}
+
+
+/*************************** Private key routines ****************************/
+
+/* Private key file magic */
+#define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
+
+/* Imports SILC implementation style private key file */
+
+SilcBool silc_pkcs_silc_import_private_key_file(unsigned char *filedata,
+ SilcUInt32 filedata_len,
+ const char *passphrase,
+ SilcUInt32 passphrase_len,
+ SilcPKCSFileEncoding encoding,
+ void **ret_private_key)
+{
+ SilcCipher aes;
+ SilcHash sha1;
+ SilcHmac sha1hmac;
+ SilcUInt32 blocklen;
+ unsigned char tmp[32], keymat[64], *data = NULL;
+ SilcUInt32 i, len, magic, mac_len;
+ SilcBool ret;
+
+ SILC_LOG_DEBUG(("Parsing SILC private key file"));
+
+ /* Check start of file and remove header from the data. */
+ len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
+ if (filedata_len < len + strlen(SILC_PKCS_PRIVATE_KEYFILE_END))
+ return FALSE;
+ for (i = 0; i < len; i++) {
+ if (*filedata != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i])
+ return FALSE;
+ filedata++;
+ }
+
+ len = filedata_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
+ strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
+
+ switch (encoding) {
+ case SILC_PKCS_FILE_BIN:
+ break;
+
+ case SILC_PKCS_FILE_BASE64:
+ data = silc_pem_decode(filedata, filedata_len, &len);
+ if (!data)
+ return FALSE;
+ filedata = data;
+ break;
+ }
+
+ memset(tmp, 0, sizeof(tmp));
+ memset(keymat, 0, sizeof(keymat));
+
+ /* Check file magic */
+ SILC_GET32_MSB(magic, filedata);
+ if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
+ SILC_LOG_ERROR(("Private key does not have correct magic"));
+ return FALSE;
+ }
+
+ /* Allocate the AES cipher */
+ if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
+ SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
+ return FALSE;
+ }
+ blocklen = silc_cipher_get_block_len(aes);
+ if (blocklen * 2 > sizeof(tmp)) {
+ silc_cipher_free(aes);
+ return FALSE;
+ }
+
+ /* Allocate SHA1 hash */
+ if (!silc_hash_alloc("sha1", &sha1)) {
+ SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
+ silc_cipher_free(aes);
+ return FALSE;
+ }
+
+ /* Allocate HMAC */
+ if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
+ SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
+ silc_hash_free(sha1);
+ silc_cipher_free(aes);
+ return FALSE;
+ }
+
+ /* Derive the decryption key from the provided key material. The key
+ is 256 bits length, and derived by taking hash of the data, then
+ re-hashing the data and the previous digest, and using the first and
+ second digest as the key. */
+ silc_hash_init(sha1);
+ silc_hash_update(sha1, passphrase, passphrase_len);
+ silc_hash_final(sha1, keymat);
+ silc_hash_init(sha1);
+ silc_hash_update(sha1, passphrase, passphrase_len);
+ silc_hash_update(sha1, keymat, 16);
+ silc_hash_final(sha1, keymat + 16);
+
+ /* Set the key to the cipher */
+ silc_cipher_set_key(aes, keymat, 256);
+
+ /* First, verify the MAC of the private key data */
+ mac_len = silc_hmac_len(sha1hmac);
+ silc_hmac_init_with_key(sha1hmac, keymat, 16);
+ silc_hmac_update(sha1hmac, filedata, len - mac_len);
+ silc_hmac_final(sha1hmac, tmp, NULL);
+ if (memcmp(tmp, filedata + (len - mac_len), mac_len)) {
+ SILC_LOG_DEBUG(("Integrity check for private key failed"));
+ memset(keymat, 0, sizeof(keymat));
+ memset(tmp, 0, sizeof(tmp));
+ silc_hmac_free(sha1hmac);
+ silc_hash_free(sha1);
+ silc_cipher_free(aes);
+ return FALSE;
+ }
+ filedata += 4;
+ len -= 4;
+
+ /* Decrypt the private key buffer */
+ silc_cipher_decrypt(aes, filedata, filedata, len - mac_len, NULL);
+ SILC_GET32_MSB(i, filedata);
+ if (i > len) {
+ SILC_LOG_DEBUG(("Bad private key length in buffer!"));
+ memset(keymat, 0, sizeof(keymat));
+ memset(tmp, 0, sizeof(tmp));
+ silc_hmac_free(sha1hmac);
+ silc_hash_free(sha1);
+ silc_cipher_free(aes);
+ return FALSE;
+ }
+ filedata += 4;
+ len = i;
+
+ /* Cleanup */
+ memset(keymat, 0, sizeof(keymat));
+ memset(tmp, 0, sizeof(tmp));
+ silc_hmac_free(sha1hmac);
+ silc_hash_free(sha1);
+ silc_cipher_free(aes);
+
+ /* Import the private key */
+ ret = silc_pkcs_silc_import_private_key(filedata, len, ret_private_key);
+
+ silc_free(data);
+
+ return ret;
+}
+
+/* Private key version */
+#define SILC_PRIVATE_KEY_VERSION_1 0x82171273
+
+/* Imports SILC implementation style private key */
+
+SilcBool silc_pkcs_silc_import_private_key(unsigned char *key,
+ SilcUInt32 key_len,
+ void **ret_private_key)
+{
+ SilcBufferStruct buf;
+ const SilcPKCSAlgorithm *pkcs;
+ SilcBufferStruct alg_key;
+ SilcSILCPrivateKey silc_privkey = NULL;
+ SilcAsn1 asn1 = NULL;
+ SilcUInt16 pkcs_len;
+ SilcUInt32 keydata_len;
+ unsigned char *pkcs_name = NULL, *key_data;
+ int ret;
+
+ SILC_LOG_DEBUG(("Parsing SILC private key"));
+
+ if (!ret_private_key)
+ return FALSE;
+
+ silc_buffer_set(&buf, key, key_len);
+
+ /* Get algorithm name and identifier */
+ ret =
+ silc_buffer_unformat(&buf,
+ SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
+ SILC_STR_END);
+ if (ret == -1) {
+ SILC_LOG_DEBUG(("Cannot decode private key buffer"));
+ goto err;
+ }
+
+ if (pkcs_len < 1 || pkcs_len > silc_buffer_truelen(&buf)) {
+ SILC_LOG_DEBUG(("Malformed private key buffer"));
+ goto err;
+ }
+
+ /* Get key data. We assume that rest of the buffer is key data. */
+ silc_buffer_pull(&buf, 2 + pkcs_len);
+ keydata_len = silc_buffer_len(&buf);
+ ret = silc_buffer_unformat(&buf,
+ SILC_STR_UI_XNSTRING(&key_data, keydata_len),
+ SILC_STR_END);
+ if (ret == -1)
+ goto err;
+
+ /* Allocate SILC private key context */
+ silc_privkey = silc_calloc(1, sizeof(*silc_privkey));
+ if (!silc_privkey)
+ goto err;
+
+ asn1 = silc_asn1_alloc();
+ if (!asn1)
+ goto err;
+
+ if (!strcmp(pkcs_name, "rsa")) {
+ /* Parse the RSA SILC private key */
+ SilcBufferStruct k;
+ SilcMPInt n, e, d, dp, dq, qp, p, q;
+ SilcMPInt version;
+ unsigned char *tmp;
+ SilcUInt32 len, ver;
+
+ /* Get PKCS object */
+ pkcs = silc_pkcs_find_algorithm(pkcs_name, "pkcs1-no-oid");
+ if (!pkcs) {
+ SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
+ goto err;
+ }
+ silc_privkey->pkcs = pkcs;
+
+ if (keydata_len < 4)
+ goto err;
+
+ silc_buffer_set(&k, key_data, keydata_len);
+
+ /* Get version. Key without the version is old style private key
+ and we need to do some computation to get it to correct format. */
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_INT(&ver),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_buffer_pull(&k, 4);
+
+ if (ver != SILC_PRIVATE_KEY_VERSION_1) {
+ len = ver;
+ } else {
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_INT(&len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_buffer_pull(&k, 4);
+ }
+
+ /* Get e */
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_XNSTRING(&tmp, len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_mp_init(&e);
+ silc_mp_bin2mp(tmp, len, &e);
+ silc_buffer_pull(&k, len);
+
+ /* Get n */
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_INT(&len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_buffer_pull(&k, 4);
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_XNSTRING(&tmp, len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_mp_init(&n);
+ silc_mp_bin2mp(tmp, len, &n);
+ silc_buffer_pull(&k, len);
+
+ /* Get d */
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_INT(&len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_buffer_pull(&k, 4);
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_XNSTRING(&tmp, len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_mp_init(&d);
+ silc_mp_bin2mp(tmp, len, &d);
+ silc_buffer_pull(&k, len);
+
+ /* Get dP */
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_INT(&len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_buffer_pull(&k, 4);
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_XNSTRING(&tmp, len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_mp_init(&dp);
+ silc_mp_bin2mp(tmp, len, &dp);
+ silc_buffer_pull(&k, len);
+
+ /* Get dQ */
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_INT(&len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_buffer_pull(&k, 4);
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_XNSTRING(&tmp, len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_mp_init(&dq);
+ silc_mp_bin2mp(tmp, len, &dq);
+ silc_buffer_pull(&k, len);
+
+ if (ver != SILC_PRIVATE_KEY_VERSION_1) {
+ /* Old version */
+
+ /* Get pQ len */
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_INT(&len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_buffer_pull(&k, 4);
+ if (silc_buffer_len(&k) < len)
+ goto err;
+ silc_buffer_pull(&k, len);
+
+ /* Get qP len */
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_INT(&len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_buffer_pull(&k, 4);
+ if (silc_buffer_len(&k) < len)
+ goto err;
+ silc_buffer_pull(&k, len);
+ } else {
+ /* New version */
+
+ /* Get qP */
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_INT(&len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_buffer_pull(&k, 4);
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_XNSTRING(&tmp, len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_mp_init(&qp);
+ silc_mp_bin2mp(tmp, len, &qp);
+ silc_buffer_pull(&k, len);
+ }
+
+ /* Get p */
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_INT(&len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_buffer_pull(&k, 4);
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_XNSTRING(&tmp, len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_mp_init(&p);
+ silc_mp_bin2mp(tmp, len, &p);
+ silc_buffer_pull(&k, len);
+
+ /* Get q */
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_INT(&len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_buffer_pull(&k, 4);
+ if (silc_buffer_unformat(&k,
+ SILC_STR_UI_XNSTRING(&tmp, len),
+ SILC_STR_END) < 0)
+ goto err;
+ silc_mp_init(&q);
+ silc_mp_bin2mp(tmp, len, &q);
+ silc_buffer_pull(&k, len);
+
+ if (ver != SILC_PRIVATE_KEY_VERSION_1) {
+ /* Old version. Compute to new version */
+ SILC_LOG_DEBUG(("Old version private key"));
+ silc_mp_init(&qp);
+ silc_mp_modinv(&qp, &q, &p);
+ }
+
+ /* Encode to PKCS #1 format */
+ silc_mp_init(&version);
+ silc_mp_set_ui(&version, 0);
+ memset(&alg_key, 0, sizeof(alg_key));
+ if (!silc_asn1_encode(asn1, &alg_key,
+ SILC_ASN1_SEQUENCE,
+ SILC_ASN1_INT(&version),
+ SILC_ASN1_INT(&n),
+ SILC_ASN1_INT(&e),
+ SILC_ASN1_INT(&d),
+ SILC_ASN1_INT(&p),
+ SILC_ASN1_INT(&q),
+ SILC_ASN1_INT(&dp),
+ SILC_ASN1_INT(&dq),
+ SILC_ASN1_INT(&qp),
+ SILC_ASN1_END, SILC_ASN1_END))
+ goto err;
+
+ silc_mp_uninit(&version);
+ silc_mp_uninit(&n);
+ silc_mp_uninit(&e);
+ silc_mp_uninit(&e);
+ silc_mp_uninit(&d);
+ silc_mp_uninit(&p);
+ silc_mp_uninit(&q);
+ silc_mp_uninit(&dp);
+ silc_mp_uninit(&dq);
+ silc_mp_uninit(&qp);
+
+ } else if (!strcmp(pkcs_name, "dsa")) {
+ SILC_NOT_IMPLEMENTED("DSA SILC Private Key");
+ goto err;
+
+ } else {
+ SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
+ goto err;
+ }
+
+ /* Import PKCS algorithm private key */
+ if (pkcs->import_private_key)
+ if (!pkcs->import_private_key(alg_key.data, silc_buffer_len(&alg_key),
+ &silc_privkey->private_key))
+ goto err;
+
+ silc_free(pkcs_name);
+ silc_asn1_free(asn1);
+
+ *ret_private_key = silc_privkey;
+
+ return TRUE;
+
+ err:
+ silc_free(pkcs_name);
+ silc_free(silc_privkey);
+ if (asn1)
+ silc_asn1_free(asn1);
+ return FALSE;
+}
+
+/* Exports private key as SILC implementation style private key file */
+
+unsigned char *
+silc_pkcs_silc_export_private_key_file(void *private_key,
+ const char *passphrase,
+ SilcUInt32 passphrase_len,
+ SilcPKCSFileEncoding encoding,
+ SilcRng rng,
+ SilcUInt32 *ret_len)
+{
+ SilcCipher aes;
+ SilcHash sha1;
+ SilcHmac sha1hmac;
+ SilcBuffer buf, enc;
+ SilcUInt32 len, blocklen, padlen, key_len;
+ unsigned char *key, *data;
+ unsigned char tmp[32], keymat[64];
+ int i;
+
+ SILC_LOG_DEBUG(("Encoding SILC private key file"));
+
+ /* Export the private key */
+ key = silc_pkcs_silc_export_private_key(private_key, &key_len);
+ if (!key)
+ return NULL;
+
+ memset(tmp, 0, sizeof(tmp));
+ memset(keymat, 0, sizeof(keymat));
+
+ /* Allocate the AES cipher */
+ if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
+ SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
+ silc_free(key);
+ return NULL;
+ }
+ blocklen = silc_cipher_get_block_len(aes);
+ if (blocklen * 2 > sizeof(tmp)) {
+ silc_cipher_free(aes);
+ silc_free(key);
+ return NULL;
+ }
+
+ /* Allocate SHA1 hash */
+ if (!silc_hash_alloc("sha1", &sha1)) {
+ SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
+ silc_cipher_free(aes);
+ return NULL;
+ }
+
+ /* Allocate HMAC */
+ if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
+ SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
+ silc_hash_free(sha1);
+ silc_cipher_free(aes);
+ return NULL;
+ }
+
+ /* Derive the encryption key from the provided key material. The key
+ is 256 bits length, and derived by taking hash of the data, then
+ re-hashing the data and the previous digest, and using the first and
+ second digest as the key. */
+ silc_hash_init(sha1);
+ silc_hash_update(sha1, passphrase, passphrase_len);
+ silc_hash_final(sha1, keymat);
+ silc_hash_init(sha1);
+ silc_hash_update(sha1, passphrase, passphrase_len);
+ silc_hash_update(sha1, keymat, 16);
+ silc_hash_final(sha1, keymat + 16);
+
+ /* Set the key to the cipher */
+ silc_cipher_set_key(aes, keymat, 256);
+
+ /* Encode the buffer to be encrypted. Add padding to it too, at least
+ block size of the cipher. */
+
+ /* Allocate buffer for encryption */
+ len = silc_hmac_len(sha1hmac);
+ padlen = 16 + (16 - ((key_len + 4) % blocklen));
+ enc = silc_buffer_alloc_size(4 + 4 + key_len + padlen + len);
+ if (!enc) {
+ silc_hmac_free(sha1hmac);
+ silc_hash_free(sha1);
+ silc_cipher_free(aes);
+ return FALSE;
+ }
+
+ /* Generate padding */
+ for (i = 0; i < padlen; i++)
+ tmp[i] = silc_rng_get_byte_fast(rng);
+
+ /* Put magic number */
+ SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
+ silc_buffer_pull(enc, 4);
+
+ /* Encode the buffer */
+ silc_buffer_format(enc,
+ SILC_STR_UI_INT(key_len),
+ SILC_STR_UI_XNSTRING(key, key_len),
+ SILC_STR_UI_XNSTRING(tmp, padlen),
+ SILC_STR_END);
+ silc_free(key);
+
+ /* Encrypt. */
+ silc_cipher_encrypt(aes, enc->data, enc->data, silc_buffer_len(enc) - len,
+ silc_cipher_get_iv(aes));
+
+ silc_buffer_push(enc, 4);
+
+ /* Compute HMAC over the encrypted data and append the MAC to data.
+ The key is the first digest of the original key material. */
+ key_len = silc_buffer_len(enc) - len;
+ silc_hmac_init_with_key(sha1hmac, keymat, 16);
+ silc_hmac_update(sha1hmac, enc->data, key_len);
+ silc_buffer_pull(enc, key_len);
+ silc_hmac_final(sha1hmac, enc->data, NULL);
+ silc_buffer_push(enc, key_len);
+
+ /* Cleanup */
+ memset(keymat, 0, sizeof(keymat));
+ memset(tmp, 0, sizeof(tmp));
+ silc_hmac_free(sha1hmac);
+ silc_hash_free(sha1);
+ silc_cipher_free(aes);
+
+ switch (encoding) {
+ case SILC_PKCS_FILE_BIN:
+ break;
+
+ case SILC_PKCS_FILE_BASE64:
+ data = silc_pem_encode_file(enc->data, silc_buffer_len(enc));
+ if (!data) {
+ silc_buffer_clear(enc);
+ silc_buffer_free(enc);
+ return NULL;
+ }
+ silc_free(silc_buffer_steal(enc, NULL));
+ silc_buffer_set(enc, data, strlen(data));
+ break;
+ }
+
+ key = enc->data;
+ key_len = silc_buffer_len(enc);
+
+ /* Encode the data and save to file */
+ len = key_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
+ strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
+ buf = silc_buffer_alloc_size(len);
+ if (!buf) {
+ silc_buffer_free(enc);
+ return NULL;
+ }
+ silc_buffer_format(buf,
+ SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
+ SILC_STR_UI_XNSTRING(key, key_len),
+ SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
+ SILC_STR_END);
+
+ silc_buffer_free(enc);
+ data = silc_buffer_steal(buf, ret_len);
+ silc_buffer_free(buf);
+
+ return data;
+}
+
+/* Exports private key as SILC implementation style private key */
+
+unsigned char *silc_pkcs_silc_export_private_key(void *private_key,
+ SilcUInt32 *ret_len)
+{
+ SilcSILCPrivateKey silc_privkey = private_key;
+ const SilcPKCSAlgorithm *pkcs = silc_privkey->pkcs;
+ SilcBufferStruct alg_key;
+ SilcBuffer buf = NULL;
+ SilcAsn1 asn1 = NULL;
+ unsigned char *prv = NULL, *key = NULL, *ret;
+ SilcUInt32 prv_len, key_len, totlen;
+
+ SILC_LOG_DEBUG(("Encoding SILC private key"));
+
+ /* Export PKCS algorithm private key */
+ if (pkcs->export_private_key)
+ prv = pkcs->export_private_key(silc_privkey->private_key, &prv_len);
+ if (!prv)
+ return NULL;
+ silc_buffer_set(&alg_key, prv, prv_len);
+
+ asn1 = silc_asn1_alloc();
+ if (!asn1)
+ goto err;
+
+ if (!strcmp(pkcs->name, "rsa")) {
+ /* Parse the PKCS #1 private key */
+ SilcMPInt n, e, d, dp, dq, qp, p, q;
+ SilcUInt32 e_len, n_len, d_len, dp_len, dq_len,
+ qp_len, p_len, q_len, len = 0;
+ unsigned char *nb, *eb, *db, *dpb, *dqb, *qpb, *pb, *qb;
+
+ if (!silc_asn1_decode(asn1, &alg_key,
+ SILC_ASN1_SEQUENCE,
+ SILC_ASN1_INT(NULL),
+ SILC_ASN1_INT(&n),
+ SILC_ASN1_INT(&e),
+ SILC_ASN1_INT(&d),
+ SILC_ASN1_INT(&p),
+ SILC_ASN1_INT(&q),
+ SILC_ASN1_INT(&dp),
+ SILC_ASN1_INT(&dq),
+ SILC_ASN1_INT(&qp),
+ SILC_ASN1_END, SILC_ASN1_END))
+ goto err;
+
+ /* Encode to SILC RSA private key */
+ eb = silc_mp_mp2bin(&e, 0, &e_len);
+ nb = silc_mp_mp2bin(&n, 0, &n_len);
+ db = silc_mp_mp2bin(&d, 0, &d_len);
+ dpb = silc_mp_mp2bin(&dp, 0, &dp_len);
+ dqb = silc_mp_mp2bin(&dq, 0, &dq_len);
+ qpb = silc_mp_mp2bin(&qp, 0, &qp_len);
+ pb = silc_mp_mp2bin(&p, 0, &p_len);
+ qb = silc_mp_mp2bin(&q, 0, &q_len);
+ len = 4 + e_len + 4 + n_len + 4 + d_len + 4+ dp_len + 4 +
+ dq_len + 4 + qp_len + 4 + p_len + 4 + q_len + 4;
+
+ buf = silc_buffer_alloc_size(len);
+ if (!buf)
+ goto err;
+ if (silc_buffer_format(buf,
+ SILC_STR_UI_INT(SILC_PRIVATE_KEY_VERSION_1),
+ SILC_STR_UI_INT(e_len),
+ SILC_STR_UI_XNSTRING(eb, e_len),
+ SILC_STR_UI_INT(n_len),
+ SILC_STR_UI_XNSTRING(nb, n_len),
+ SILC_STR_UI_INT(d_len),
+ SILC_STR_UI_XNSTRING(db, d_len),
+ SILC_STR_UI_INT(dp_len),
+ SILC_STR_UI_XNSTRING(dpb, dp_len),
+ SILC_STR_UI_INT(dq_len),
+ SILC_STR_UI_XNSTRING(dqb, dq_len),
+ SILC_STR_UI_INT(qp_len),
+ SILC_STR_UI_XNSTRING(qpb, qp_len),
+ SILC_STR_UI_INT(p_len),
+ SILC_STR_UI_XNSTRING(pb, p_len),
+ SILC_STR_UI_INT(q_len),
+ SILC_STR_UI_XNSTRING(qb, q_len),
+ SILC_STR_END) < 0)
+ goto err;
+
+ key = silc_buffer_steal(buf, &key_len);
+ silc_buffer_free(buf);
+ silc_free(nb);
+ silc_free(eb);
+ silc_free(db);
+ silc_free(dpb);
+ silc_free(dqb);
+ silc_free(qpb);
+ silc_free(pb);
+ silc_free(qb);
+
+ } else if (!strcmp(pkcs->name, "dsa")) {
+ SILC_NOT_IMPLEMENTED("SILC DSA Private Key");
+ goto err;
+
+ } else {
+ SILC_LOG_DEBUG(("Unsupported PKCS algorithm"));
+ goto err;
+ }
+
+ /* Encode SILC private key */
+ totlen = 2 + strlen(pkcs->name) + key_len;
+ buf = silc_buffer_alloc_size(totlen);
+ if (!buf)
+ goto err;
+ if (silc_buffer_format(buf,
+ SILC_STR_UI_SHORT(strlen(pkcs->name)),
+ SILC_STR_UI32_STRING(pkcs->name),
+ SILC_STR_UI_XNSTRING(key, key_len),
+ SILC_STR_END) < 0)
+ goto err;
+
+ ret = silc_buffer_steal(buf, ret_len);
+ silc_buffer_free(buf);
+ silc_free(prv);
+ silc_free(key);
+ silc_asn1_free(asn1);
+
+ return ret;
+
+ err:
+ silc_free(prv);
+ silc_free(key);
+ if (buf)
+ silc_buffer_free(buf);
+ return NULL;
+}
+
+/* Return key length */
+
+SilcUInt32 silc_pkcs_silc_private_key_bitlen(void *private_key)
+{
+ SilcSILCPrivateKey silc_privkey = private_key;
+ return silc_privkey->pkcs->private_key_bitlen(silc_privkey->private_key);
+}
+
+/* Frees private key */
+
+void silc_pkcs_silc_private_key_free(void *private_key)
+{
+ SilcSILCPrivateKey silc_privkey = private_key;
+
+ silc_privkey->pkcs->private_key_free(silc_privkey->private_key);
+
+ silc_free(silc_privkey);
+}
+
+
+/***************************** PKCS operations ******************************/
+
+/* Encrypts as specified in SILC protocol specification */
+
+SilcBool silc_pkcs_silc_encrypt(void *public_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *dst,
+ SilcUInt32 dst_size,
+ SilcUInt32 *ret_dst_len)
+{
+ SilcSILCPublicKey silc_pubkey = public_key;
+
+ if (!silc_pubkey->pkcs->encrypt)
+ return FALSE;
+
+ return silc_pubkey->pkcs->encrypt(silc_pubkey->public_key,
+ src, src_len,
+ dst, dst_size, ret_dst_len);
+}
+
+/* Decrypts as specified in SILC protocol specification */
+
+SilcBool silc_pkcs_silc_decrypt(void *private_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *dst,
+ SilcUInt32 dst_size,
+ SilcUInt32 *ret_dst_len)
+{
+ SilcSILCPrivateKey silc_privkey = private_key;
+
+ if (!silc_privkey->pkcs->decrypt)
+ return FALSE;
+
+ return silc_privkey->pkcs->decrypt(silc_privkey->private_key,
+ src, src_len,
+ dst, dst_size, ret_dst_len);
+}
+
+/* Signs as specified in SILC protocol specification */
+
+SilcBool silc_pkcs_silc_sign(void *private_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *signature,
+ SilcUInt32 signature_size,
+ SilcUInt32 *ret_signature_len,
+ SilcHash hash)
+{
+ SilcSILCPrivateKey silc_privkey = private_key;
+
+ if (!silc_privkey->pkcs->sign)
+ return FALSE;
+
+ return silc_privkey->pkcs->sign(silc_privkey->private_key,
+ src, src_len,
+ signature, signature_size,
+ ret_signature_len, hash);
+}
+
+/* Verifies as specified in SILC protocol specification */
+
+SilcBool silc_pkcs_silc_verify(void *public_key,
+ unsigned char *signature,
+ SilcUInt32 signature_len,
+ unsigned char *data,
+ SilcUInt32 data_len,
+ SilcHash hash)
+{
+ SilcSILCPublicKey silc_pubkey = public_key;
+
+ if (!silc_pubkey->pkcs->verify)
+ return FALSE;
+
+ return silc_pubkey->pkcs->verify(silc_pubkey->public_key,
+ signature, signature_len,
+ data, data_len, hash);
+}
--- /dev/null
+/*
+
+ silcpk.h
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 1997 - 2005 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+/****h* silccrypt/SILC Public Key Interface
+ *
+ * DESCRIPTION
+ *
+ * This interface implements the SILC protocol style public key, as defined
+ * by the SILC protocol specification.
+ *
+ ***/
+
+#ifndef SILCPK_H
+#define SILCPK_H
+
+/****s* silccrypt/SilcPubkeyAPI/SilcPublicKeyIdentifier
+ *
+ * NAME
+ *
+ * typedef struct { ... } *SilcPublicKeyIdentifier,
+ * SilcPublicKeyIdentifierStruct;
+ *
+ * DESCRIPTION
+ *
+ * This structure contains the SILC Public Key identifier. Note that
+ * some of the fields may be NULL.
+ *
+ * SOURCE
+ */
+typedef struct {
+ char *username;
+ char *host;
+ char *realname;
+ char *email;
+ char *org;
+ char *country;
+} *SilcPublicKeyIdentifier, SilcPublicKeyIdentifierStruct;
+/***/
+
+/****s* silccrypt/SilcPubkeyAPI/SilcSILCPublicKey
+ *
+ * NAME
+ *
+ * typedef struct { ... } *SilcSILCPublicKey;
+ *
+ * DESCRIPTION
+ *
+ * This structure defines the SILC protocol style public key. User
+ * doesn't have to access this structure usually, except when access to
+ * the identifier is required. The silc_pkcs_get_context for the
+ * PKCS type SILC_PKCS_SILC returns this context.
+ *
+ * SOURCE
+ */
+typedef struct {
+ SilcPublicKeyIdentifierStruct identifier;
+ const SilcPKCSAlgorithm *pkcs; /* PKCS algorithm */
+ void *public_key; /* MPKCS algorithm specific public key */
+} *SilcSILCPublicKey;
+/***/
+
+/****s* silccrypt/SilcPubkeyAPI/SilcSILCPrivateKey
+ *
+ * NAME
+ *
+ * typedef struct { ... } *SilcSILCPrivateKey;
+ *
+ * DESCRIPTION
+ *
+ * This structure defines the SILC protocol implementation specific
+ * private key. This structure isn't usually needed by the user.
+ *
+ * SOURCE
+ */
+typedef struct {
+ const SilcPKCSAlgorithm *pkcs; /* PKCS algorithm */
+ void *private_key; /* PKCS algorithm specific private key */
+} *SilcSILCPrivateKey;
+/***/
+
+/****f* silccrypt/SilcPubkeyAPI/silc_pkcs_silc_generate_key
+ *
+ * SYNOPSIS
+ *
+ * SilcBool silc_pkcs_silc_generate_key(const char *algorithm,
+ * const char *scheme,
+ * SilcUInt32 bits_key_len,
+ * SilcRng rng,
+ * SilcPublicKey *ret_public_key,
+ * SilcPrivateKey *ret_private_key)
+ *
+ * DESCRIPTION
+ *
+ * Generate a new SILC key pair of the algorithm type `algorithm' with
+ * the key length in bits of `bits_key_len'. The `scheme' may be NULL.
+ * Returns FALSE if key generation failed.
+ *
+ * EXAMPLE
+ *
+ * // Generate RSA key pair with 2048 bit key length, using PKCS #1
+ * // no OID scheme.
+ * silc_pkcs_silc_generate_key("rsa", "pkcs1-no-oid", 2048,
+ * rng, &public_key, &private_key);
+ *
+ ***/
+SilcBool silc_pkcs_silc_generate_key(const char *algorithm,
+ const char *scheme,
+ SilcUInt32 bits_key_len,
+ const char *identifier,
+ SilcRng rng,
+ SilcPublicKey *ret_public_key,
+ SilcPrivateKey *ret_private_key);
+
+/****f* silccrypt/SilcPubkeyAPI/silc_pkcs_silc_decode_identifier
+ *
+ * SYNOPSIS
+ *
+ * char *silc_pkcs_silc_encode_identifier(char *username, char *host,
+ * char *realname, char *email,
+ * char *org, char *country)
+ *
+ * DESCRIPTION
+ *
+ * Encodes and returns SILC public key identifier. If some of the
+ * arguments are NULL those are not encoded into the identifier string.
+ * Protocol says that at least username and host must be provided.
+ * Caller must free the returned identifier string.
+ *
+ ***/
+char *silc_pkcs_silc_encode_identifier(char *username, char *host,
+ char *realname, char *email,
+ char *org, char *country);
+
+/****f* silccrypt/SilcPubkeyAPI/silc_pkcs_silc_decode_identifier
+ *
+ * SYNOPSIS
+ *
+ * SilcBool silc_pkcs_silc_decode_identifier(const char *identifier,
+ * SilcPublicKeyIdentifier ident);
+ *
+ * DESCRIPTION
+ *
+ * Decodes SILC protocol public key identifier `identifier' into the
+ * the `ident' structure. Returns FALSE if the identifier is not valid
+ * identifier string.
+ *
+ ***/
+SilcBool silc_pkcs_silc_decode_identifier(const char *identifier,
+ SilcPublicKeyIdentifier ident);
+
+#endif /* SILCPK_H */
--- /dev/null
+/*
+
+ silcpk_i.h
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2005 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#ifndef SILCPK_I_H
+#define SILCPK_I_H
+
+/* Public and private key file headers */
+#define SILC_PKCS_PUBLIC_KEYFILE_BEGIN "-----BEGIN SILC PUBLIC KEY-----\n"
+#define SILC_PKCS_PUBLIC_KEYFILE_END "\n-----END SILC PUBLIC KEY-----\n"
+#define SILC_PKCS_PRIVATE_KEYFILE_BEGIN "-----BEGIN SILC PRIVATE KEY-----\n"
+#define SILC_PKCS_PRIVATE_KEYFILE_END "\n-----END SILC PRIVATE KEY-----\n"
+
+const SilcPKCSAlgorithm *silc_pkcs_silc_get_algorithm(void *public_key);
+SilcBool silc_pkcs_silc_import_public_key_file(unsigned char *filedata,
+ SilcUInt32 filedata_len,
+ SilcPKCSFileEncoding encoding,
+ void **ret_public_key);
+SilcBool silc_pkcs_silc_import_public_key(unsigned char *key,
+ SilcUInt32 key_len,
+ void **ret_public_key);
+unsigned char *
+silc_pkcs_silc_export_public_key_file(void *public_key,
+ SilcPKCSFileEncoding encoding,
+ SilcUInt32 *ret_len);
+unsigned char *silc_pkcs_silc_export_public_key(void *public_key,
+ SilcUInt32 *ret_len);
+SilcUInt32 silc_pkcs_silc_public_key_bitlen(void *public_key);
+void *silc_pkcs_silc_public_key_copy(void *public_key);
+SilcBool silc_pkcs_silc_public_key_compare(void *key1, void *key2);
+void silc_pkcs_silc_public_key_free(void *public_key);
+SilcBool silc_pkcs_silc_import_private_key_file(unsigned char *filedata,
+ SilcUInt32 filedata_len,
+ const char *passphrase,
+ SilcUInt32 passphrase_len,
+ SilcPKCSFileEncoding encoding,
+ void **ret_private_key);
+SilcBool silc_pkcs_silc_import_private_key(unsigned char *key,
+ SilcUInt32 key_len,
+ void **ret_private_key);
+unsigned char *
+silc_pkcs_silc_export_private_key_file(void *private_key,
+ const char *passphrase,
+ SilcUInt32 passphrase_len,
+ SilcPKCSFileEncoding encoding,
+ SilcRng rng,
+ SilcUInt32 *ret_len);
+unsigned char *silc_pkcs_silc_export_private_key(void *private_key,
+ SilcUInt32 *ret_len);
+SilcUInt32 silc_pkcs_silc_private_key_bitlen(void *private_key);
+void silc_pkcs_silc_private_key_free(void *private_key);
+SilcBool silc_pkcs_silc_encrypt(void *public_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *dst,
+ SilcUInt32 dst_size,
+ SilcUInt32 *ret_dst_len);
+SilcBool silc_pkcs_silc_decrypt(void *private_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *dst,
+ SilcUInt32 dst_size,
+ SilcUInt32 *ret_dst_len);
+SilcBool silc_pkcs_silc_sign(void *private_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *signature,
+ SilcUInt32 signature_size,
+ SilcUInt32 *ret_signature_len,
+ SilcHash hash);
+SilcBool silc_pkcs_silc_verify(void *public_key,
+ unsigned char *signature,
+ SilcUInt32 signature_len,
+ unsigned char *data,
+ SilcUInt32 data_len,
+ SilcHash hash);
+
+#endif /* SILCPK_I_H */
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2005 Pekka Riikonen
+ Copyright (C) 1997 - 2006 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* $Id$ */
#include "silc.h"
-
-#include "rsa.h"
-
-/* The main SILC PKCS structure. */
-struct SilcPKCSStruct {
- void *context; /* Algorithm internal context */
- SilcPKCSObject *pkcs; /* Algorithm implementation */
- SilcUInt32 key_len; /* Key length in bits */
-};
+#include "silcpk_i.h"
+#include "silcpkcs1_i.h"
#ifndef SILC_EPOC
/* Dynamically registered list of PKCS. */
SilcDList silc_pkcs_list = NULL;
+SilcDList silc_pkcs_alg_list = NULL;
#define SILC_PKCS_LIST silc_pkcs_list
+#define SILC_PKCS_ALG_LIST silc_pkcs_alg_list
#else
#define SILC_PKCS_LIST TRUE
+#define SILC_PKCS_ALG_LIST TRUE
#endif /* SILC_EPOC */
/* Static list of PKCS for silc_pkcs_register_default(). */
const SilcPKCSObject silc_default_pkcs[] =
{
- /* RSA with PKCS #1 for SILC PKCS */
- { "rsa", SILC_PKCS_SILC,
- silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
- silc_rsa_get_private_key, silc_rsa_set_public_key,
- silc_rsa_set_private_key, silc_rsa_context_len,
- silc_pkcs1_encrypt, silc_pkcs1_decrypt,
- silc_pkcs1_sign, silc_pkcs1_verify },
-
- /* RSASSA-PKCS1-V1_5 for SSH2 PKCS */
-/*
- { "rsa", SILC_PKCS_SSH2,
- silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
- silc_rsa_get_private_key, silc_rsa_set_public_key,
- silc_rsa_set_private_key, silc_rsa_context_len,
- silc_pkcs1_encrypt, silc_pkcs1_decrypt,
- silc_pkcs1_sign, silc_pkcs1_verify },
-*/
+ /* SILC PKCS */
+ {
+ SILC_PKCS_SILC,
+ silc_pkcs_silc_get_algorithm,
+ silc_pkcs_silc_import_public_key_file,
+ silc_pkcs_silc_import_public_key,
+ silc_pkcs_silc_export_public_key_file,
+ silc_pkcs_silc_export_public_key,
+ silc_pkcs_silc_public_key_bitlen,
+ silc_pkcs_silc_public_key_copy,
+ silc_pkcs_silc_public_key_compare,
+ silc_pkcs_silc_public_key_free,
+ silc_pkcs_silc_import_private_key_file,
+ silc_pkcs_silc_import_private_key,
+ silc_pkcs_silc_export_private_key_file,
+ silc_pkcs_silc_export_private_key,
+ silc_pkcs_silc_private_key_bitlen,
+ silc_pkcs_silc_private_key_free,
+ silc_pkcs_silc_encrypt,
+ silc_pkcs_silc_decrypt,
+ silc_pkcs_silc_sign,
+ silc_pkcs_silc_verify,
+ },
+
+ {
+ 0, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL
+ }
+};
+
+/* Builtin PKCS algorithms */
+const SilcPKCSAlgorithm silc_default_pkcs_alg[] =
+{
+ /* PKCS #1, Version 1.5 without hash OIDs */
+ {
+ "rsa",
+ "pkcs1-no-oid",
+ "sha1,md5",
+ silc_pkcs1_generate_key,
+ silc_pkcs1_import_public_key,
+ silc_pkcs1_export_public_key,
+ silc_pkcs1_public_key_bitlen,
+ silc_pkcs1_public_key_copy,
+ silc_pkcs1_public_key_compare,
+ silc_pkcs1_public_key_free,
+ silc_pkcs1_import_private_key,
+ silc_pkcs1_export_private_key,
+ silc_pkcs1_private_key_bitlen,
+ silc_pkcs1_private_key_free,
+ silc_pkcs1_encrypt,
+ silc_pkcs1_decrypt,
+ silc_pkcs1_sign_no_oid,
+ silc_pkcs1_verify_no_oid
+ },
+
+ /* PKCS #1, Version 1.5 */
+ {
+ "rsa",
+ "pkcs1",
+ "sha1,md5",
+ silc_pkcs1_generate_key,
+ silc_pkcs1_import_public_key,
+ silc_pkcs1_export_public_key,
+ silc_pkcs1_public_key_bitlen,
+ silc_pkcs1_public_key_copy,
+ silc_pkcs1_public_key_compare,
+ silc_pkcs1_public_key_free,
+ silc_pkcs1_import_private_key,
+ silc_pkcs1_export_private_key,
+ silc_pkcs1_private_key_bitlen,
+ silc_pkcs1_private_key_free,
+ silc_pkcs1_encrypt,
+ silc_pkcs1_decrypt,
+ silc_pkcs1_sign,
+ silc_pkcs1_verify
+ },
- { NULL, 0, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL }
+ {
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL
+ }
};
-/* Register a new PKCS into SILC. This is used at the initialization of
- the SILC. */
+/* Register a new PKCS into SILC. */
SilcBool silc_pkcs_register(const SilcPKCSObject *pkcs)
{
#ifndef SILC_EPOC
- SilcPKCSObject *new;
+ SilcPKCSObject *newpkcs;
- SILC_LOG_DEBUG(("Registering new PKCS `%s'", pkcs->name));
+ SILC_LOG_DEBUG(("Registering new PKCS"));
/* Check if exists already */
if (silc_pkcs_list) {
SilcPKCSObject *entry;
silc_dlist_start(silc_pkcs_list);
while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
- if (!strcmp(entry->name, pkcs->name) &&
- entry->type == pkcs->type)
+ if (entry->type == pkcs->type)
return FALSE;
}
}
- new = silc_calloc(1, sizeof(*new));
- new->name = strdup(pkcs->name);
- new->type = pkcs->type;
- new->init = pkcs->init;
- new->clear_keys = pkcs->clear_keys;
- new->get_public_key = pkcs->get_public_key;
- new->get_private_key = pkcs->get_private_key;
- new->set_public_key = pkcs->set_public_key;
- new->set_private_key = pkcs->set_private_key;
- new->context_len = pkcs->context_len;
- new->encrypt = pkcs->encrypt;
- new->decrypt = pkcs->decrypt;
- new->sign = pkcs->sign;
- new->verify = pkcs->verify;
+ newpkcs = silc_calloc(1, sizeof(*newpkcs));
+ if (!newpkcs)
+ return FALSE;
+ *newpkcs = *pkcs;
/* Add to list */
if (silc_pkcs_list == NULL)
silc_pkcs_list = silc_dlist_init();
- silc_dlist_add(silc_pkcs_list, new);
+ silc_dlist_add(silc_pkcs_list, newpkcs);
#endif /* SILC_EPOC */
return TRUE;
while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
if (pkcs == SILC_ALL_PKCS || entry == pkcs) {
silc_dlist_del(silc_pkcs_list, entry);
- silc_free(entry->name);
silc_free(entry);
if (silc_dlist_count(silc_pkcs_list) == 0) {
return FALSE;
}
-/* Function that registers all the default PKCS (all builtin PKCS).
- The application may use this to register the default PKCS if specific
- PKCS in any specific order is not wanted. */
+/* Register algorithm */
-SilcBool silc_pkcs_register_default(void)
+SilcBool silc_pkcs_algorithm_register(const SilcPKCSAlgorithm *pkcs)
{
#ifndef SILC_EPOC
- int i;
+ SilcPKCSAlgorithm *newalg;
- for (i = 0; silc_default_pkcs[i].name; i++)
- silc_pkcs_register(&(silc_default_pkcs[i]));
-
-#endif /* SILC_EPOC */
- return TRUE;
-}
+ SILC_LOG_DEBUG(("Registering new PKCS algorithm %s",
+ pkcs->name));
-SilcBool silc_pkcs_unregister_all(void)
-{
-#ifndef SILC_EPOC
- SilcPKCSObject *entry;
+ /* Check if exists already */
+ if (silc_pkcs_alg_list) {
+ SilcPKCSAlgorithm *entry;
+ silc_dlist_start(silc_pkcs_alg_list);
+ while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
+ if (!strcmp(entry->name, pkcs->name) &&
+ entry->scheme && pkcs->scheme &&
+ !strcmp(entry->scheme, pkcs->scheme))
+ return FALSE;
+ }
+ }
- if (!silc_pkcs_list)
+ newalg = silc_calloc(1, sizeof(*newalg));
+ if (!newalg)
return FALSE;
- silc_dlist_start(silc_pkcs_list);
- while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
- silc_pkcs_unregister(entry);
- if (!silc_pkcs_list)
- break;
+ *newalg = *pkcs;
+ newalg->name = strdup(pkcs->name);
+ if (!newalg->name)
+ return FALSE;
+ if (pkcs->scheme) {
+ newalg->scheme = strdup(pkcs->scheme);
+ if (!newalg->scheme)
+ return FALSE;
}
+ newalg->hash = strdup(pkcs->hash);
+ if (!newalg->hash)
+ return FALSE;
+
+ /* Add to list */
+ if (silc_pkcs_alg_list == NULL)
+ silc_pkcs_alg_list = silc_dlist_init();
+ silc_dlist_add(silc_pkcs_alg_list, newalg);
+
#endif /* SILC_EPOC */
return TRUE;
}
-/* Allocates a new SilcPKCS object. The new allocated object is returned
- to the 'new_pkcs' argument. */
+/* Unregister algorithm */
-SilcBool silc_pkcs_alloc(const unsigned char *name, SilcPKCSType type,
- SilcPKCS *new_pkcs)
+SilcBool silc_pkcs_algorithm_unregister(SilcPKCSAlgorithm *pkcs)
{
- SilcPKCSObject *entry = NULL;
+#ifndef SILC_EPOC
+ SilcPKCSAlgorithm*entry;
- SILC_LOG_DEBUG(("Allocating new PKCS object"));
+ SILC_LOG_DEBUG(("Unregistering PKCS algorithm"));
-#ifndef SILC_EPOC
- if (silc_pkcs_list) {
- silc_dlist_start(silc_pkcs_list);
- while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
- if (!strcmp(entry->name, name) && entry->type == type)
- break;
- }
- }
-#else
- {
- /* On EPOC which don't have globals we check our constant hash list. */
- int i;
- for (i = 0; silc_default_pkcs[i].name; i++) {
- if (!strcmp(silc_default_pkcs[i].name, name) &&
- silc_default_pkcs[i].type == type) {
- entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
- break;
+ if (!silc_pkcs_alg_list)
+ return FALSE;
+
+ silc_dlist_start(silc_pkcs_alg_list);
+ while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
+ if (pkcs == SILC_ALL_PKCS_ALG || entry == pkcs) {
+ silc_dlist_del(silc_pkcs_alg_list, entry);
+ silc_free(entry->name);
+ silc_free(entry->scheme);
+ silc_free(entry->hash);
+ silc_free(entry);
+
+ if (silc_dlist_count(silc_pkcs_alg_list) == 0) {
+ silc_dlist_uninit(silc_pkcs_alg_list);
+ silc_pkcs_alg_list = NULL;
}
- }
- }
-#endif /* SILC_EPOC */
- if (entry) {
- *new_pkcs = silc_calloc(1, sizeof(**new_pkcs));
- (*new_pkcs)->pkcs = entry;
- (*new_pkcs)->context = silc_calloc(1, entry->context_len());
- return TRUE;
+ return TRUE;
+ }
}
+#endif /* SILC_EPOC */
return FALSE;
}
-/* Free's the PKCS object */
+/* Function that registers all the default PKCS and PKCS algorithms. */
-void silc_pkcs_free(SilcPKCS pkcs)
+SilcBool silc_pkcs_register_default(void)
{
- if (pkcs) {
- pkcs->pkcs->clear_keys(pkcs->context);
- silc_free(pkcs->context);
- }
- silc_free(pkcs);
-}
+#ifndef SILC_EPOC
+ int i;
+
+ for (i = 0; silc_default_pkcs[i].type; i++)
+ silc_pkcs_register(&(silc_default_pkcs[i]));
-/* Return TRUE if PKCS algorithm `name' is supported. */
+ for (i = 0; silc_default_pkcs_alg[i].name; i++)
+ silc_pkcs_algorithm_register(&(silc_default_pkcs_alg[i]));
+
+#endif /* SILC_EPOC */
+ return TRUE;
+}
-SilcBool silc_pkcs_is_supported(const unsigned char *name)
+SilcBool silc_pkcs_unregister_all(void)
{
#ifndef SILC_EPOC
SilcPKCSObject *entry;
+ SilcPKCSAlgorithm *alg;
if (silc_pkcs_list) {
silc_dlist_start(silc_pkcs_list);
while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
- if (!strcmp(entry->name, name))
- return TRUE;
+ silc_pkcs_unregister(entry);
+ if (!silc_pkcs_list)
+ break;
}
}
-#else
- {
- int i;
- for (i = 0; silc_default_pkcs[i].name; i++)
- if (!strcmp(silc_default_pkcs[i].name, name))
- return TRUE;
+
+ if (silc_pkcs_alg_list) {
+ silc_dlist_start(silc_pkcs_alg_list);
+ while ((alg = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
+ silc_pkcs_algorithm_unregister(alg);
+ if (!silc_pkcs_alg_list)
+ break;
+ }
}
+
#endif /* SILC_EPOC */
- return FALSE;
+ return TRUE;
}
/* Returns comma separated list of supported PKCS algorithms */
char *silc_pkcs_get_supported(void)
{
- SilcPKCSObject *entry;
+ SilcPKCSAlgorithm *entry;
char *list = NULL;
int len = 0;
#ifndef SILC_EPOC
- if (silc_pkcs_list) {
- silc_dlist_start(silc_pkcs_list);
- while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
+ if (silc_pkcs_alg_list) {
+ silc_dlist_start(silc_pkcs_alg_list);
+ while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
len += strlen(entry->name);
list = silc_realloc(list, len + 1);
+ if (!list)
+ return NULL;
memcpy(list + (len - strlen(entry->name)),
entry->name, strlen(entry->name));
#else
{
int i;
- for (i = 0; silc_default_pkcs[i].name; i++) {
- entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
+ for (i = 0; silc_default_pkcs_alg[i].name; i++) {
+ entry = (SilcPKCSAlgorithm *)&(silc_default_pkcs_alg[i]);
len += strlen(entry->name);
list = silc_realloc(list, len + 1);
+ if (!list)
+ return NULL;
memcpy(list + (len - strlen(entry->name)),
entry->name, strlen(entry->name));
return list;
}
-/* Generate new key pair into the `pkcs' context. */
+/* Finds PKCS object */
-SilcBool silc_pkcs_generate_key(SilcPKCS pkcs, SilcUInt32 bits_key_len,
- SilcRng rng)
+const SilcPKCSObject *silc_pkcs_find_pkcs(SilcPKCSType type)
{
- SilcBool ret = pkcs->pkcs->init(pkcs->context, bits_key_len, rng);
- if (ret)
- pkcs->key_len = bits_key_len;
- return ret;
-}
-
-/* Returns the length of the key */
+ SilcPKCSObject *entry;
-SilcUInt32 silc_pkcs_get_key_len(SilcPKCS pkcs)
-{
- return pkcs->key_len;
-}
+#ifndef SILC_EPOC
+ if (silc_pkcs_list) {
+ silc_dlist_start(silc_pkcs_list);
+ while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
+ if (entry->type == type)
+ return (const SilcPKCSObject *)entry;
+ }
+ }
+#else
+ {
+ int i;
+ for (i = 0; silc_default_pkcs[i].name; i++) {
+ entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
+ if (entry->type == type)
+ return (const SilcPKCSObject *)entry;
+ }
+ }
+#endif /* SILC_EPOC */
-const char *silc_pkcs_get_name(SilcPKCS pkcs)
-{
- return pkcs->pkcs->name;
+ return NULL;
}
-/* Returns SILC style public key */
+/* Finds PKCS algorithms object */
-unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, SilcUInt32 *len)
+const SilcPKCSAlgorithm *silc_pkcs_find_algorithm(const char *algorithm,
+ const char *scheme)
{
- return pkcs->pkcs->get_public_key(pkcs->context, len);
-}
+ SilcPKCSAlgorithm *entry;
-/* Returns SILC style private key */
+#ifndef SILC_EPOC
+ if (silc_pkcs_alg_list) {
+ silc_dlist_start(silc_pkcs_alg_list);
+ while ((entry = silc_dlist_get(silc_pkcs_alg_list)) != SILC_LIST_END) {
+ if (!strcmp(entry->name, algorithm) &&
+ (!scheme || !entry->scheme || !strcmp(entry->scheme, scheme)))
+ return (const SilcPKCSAlgorithm *)entry;
+ }
+ }
+#else
+ {
+ int i;
+ for (i = 0; silc_default_pkcs_alg[i].name; i++) {
+ entry = (SilcPKCSAlgorithm *)&(silc_default_pkcs_alg[i]);
+ if (!strcmp(entry->name, algorithm) &&
+ (!scheme || !entry->scheme || !strcmp(entry->scheme, scheme)))
+ return (const SilcPKCSAlgorithm *)entry;
+ }
+ }
+#endif /* SILC_EPOC */
-unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, SilcUInt32 *len)
-{
- return pkcs->pkcs->get_private_key(pkcs->context, len);
+ return NULL;
}
-/* Sets public key from SilcPublicKey. */
+/* Returns PKCS context */
-SilcUInt32 silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
+const SilcPKCSObject *silc_pkcs_get_pkcs(SilcPublicKey public_key)
{
- pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
- public_key->pk_len);
- return pkcs->key_len;
+ return public_key->pkcs;
}
-/* Sets public key from data. */
+/* Returns PKCS algorithm context */
-SilcUInt32 silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
- SilcUInt32 pk_len)
+const SilcPKCSAlgorithm *silc_pkcs_get_algorithm(SilcPublicKey public_key)
{
- pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, pk, pk_len);
- return pkcs->key_len;
+ return public_key->pkcs->get_algorithm(public_key->public_key);
}
-/* Sets private key from SilcPrivateKey. */
+/* Return algorithm name */
-SilcUInt32 silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
+const char *silc_pkcs_get_name(SilcPublicKey public_key)
{
- SilcUInt32 key_len;
- key_len = pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
- private_key->prv_len);
- if (!pkcs->key_len)
- pkcs->key_len = key_len;
- return pkcs->key_len;
+ const SilcPKCSAlgorithm *pkcs = silc_pkcs_get_algorithm(public_key);
+ return pkcs->name;
}
-/* Sets private key from data. */
+/* Returns PKCS type */
-SilcUInt32 silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
- SilcUInt32 prv_len)
+SilcPKCSType silc_pkcs_get_type(SilcPublicKey public_key)
{
- SilcUInt32 key_len;
- key_len = pkcs->pkcs->set_private_key(pkcs->context, prv, prv_len);
- if (!pkcs->key_len)
- pkcs->key_len = key_len;
- return pkcs->key_len;
+ return public_key->pkcs->type;
}
-/* Encrypts */
+/* Allocates new public key from the key data */
-SilcBool silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
- unsigned char *dst, SilcUInt32 *dst_len)
+SilcBool silc_pkcs_public_key_alloc(SilcPKCSType type,
+ unsigned char *key,
+ SilcUInt32 key_len,
+ SilcPublicKey *ret_public_key)
{
- return pkcs->pkcs->encrypt(pkcs->context, src, src_len, dst, dst_len);
-}
+ const SilcPKCSObject *pkcs;
+ SilcPublicKey public_key;
-/* Decrypts */
+ if (!ret_public_key)
+ return FALSE;
-SilcBool silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
- unsigned char *dst, SilcUInt32 *dst_len)
-{
- return pkcs->pkcs->decrypt(pkcs->context, src, src_len, dst, dst_len);
-}
+ /* Allocate public key context */
+ public_key = silc_calloc(1, sizeof(*public_key));
+ if (!public_key)
+ return FALSE;
-/* Generates signature */
+ public_key->pkcs = pkcs = silc_pkcs_find_pkcs(type);
+ if (!public_key->pkcs) {
+ silc_free(public_key);
+ return FALSE;
+ }
-SilcBool silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
- unsigned char *dst, SilcUInt32 *dst_len)
-{
- return pkcs->pkcs->sign(pkcs->context, src, src_len, dst, dst_len);
-}
+ /* Import the PKCS public key */
+ if (!pkcs->import_public_key(key, key_len, &public_key->public_key)) {
+ silc_free(public_key);
+ return FALSE;
+ }
-/* Verifies signature */
+ *ret_public_key = public_key;
-SilcBool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
- SilcUInt32 signature_len, unsigned char *data,
- SilcUInt32 data_len)
-{
- return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
- data, data_len);
+ return TRUE;
}
-/* Generates signature with hash. The hash is signed. */
+/* Frees the public key */
-SilcBool silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
- unsigned char *src, SilcUInt32 src_len,
- unsigned char *dst, SilcUInt32 *dst_len)
+void silc_pkcs_public_key_free(SilcPublicKey public_key)
{
- unsigned char hashr[SILC_HASH_MAXLEN];
- SilcUInt32 hash_len;
- int ret;
-
- silc_hash_make(hash, src, src_len, hashr);
- hash_len = silc_hash_len(hash);
-
- SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
-
- ret = pkcs->pkcs->sign(pkcs->context, hashr, hash_len, dst, dst_len);
- memset(hashr, 0, sizeof(hashr));
-
- return ret;
+ public_key->pkcs->public_key_free(public_key->public_key);
}
-/* Verifies signature with hash. The `data' is hashed and verified against
- the `signature'. */
+/* Exports public key */
-SilcBool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
- unsigned char *signature,
- SilcUInt32 signature_len,
- unsigned char *data,
- SilcUInt32 data_len)
+unsigned char *silc_pkcs_public_key_encode(SilcPublicKey public_key,
+ SilcUInt32 *ret_len)
{
- unsigned char hashr[SILC_HASH_MAXLEN];
- SilcUInt32 hash_len;
- int ret;
-
- silc_hash_make(hash, data, data_len, hashr);
- hash_len = silc_hash_len(hash);
-
- SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
-
- ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
- hashr, hash_len);
- memset(hashr, 0, sizeof(hashr));
-
- return ret;
+ return public_key->pkcs->export_public_key(public_key->public_key,
+ ret_len);
}
-/* Encodes and returns SILC public key identifier. If some of the
- arguments is NULL those are not encoded into the identifier string.
- Protocol says that at least username and host must be provided. */
+/* Return key length */
-char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
- char *email, char *org, char *country)
+SilcUInt32 silc_pkcs_public_key_get_len(SilcPublicKey public_key)
{
- SilcBuffer buf;
- char *identifier;
- SilcUInt32 len, tlen = 0;
-
- if (!username || !host)
- return NULL;
-
- len = (username ? strlen(username) : 0) +
- (host ? strlen(host) : 0) +
- (realname ? strlen(realname) : 0) +
- (email ? strlen(email) : 0) +
- (org ? strlen(org) : 0) +
- (country ? strlen(country) : 0);
-
- if (len < 3)
- return NULL;
-
- len += 3 + 5 + 5 + 4 + 4 + 4;
- buf = silc_buffer_alloc(len);
- silc_buffer_pull_tail(buf, len);
-
- if (username) {
- silc_buffer_format(buf,
- SILC_STR_UI32_STRING("UN="),
- SILC_STR_UI32_STRING(username),
- SILC_STR_END);
- silc_buffer_pull(buf, 3 + strlen(username));
- tlen = 3 + strlen(username);
- }
-
- if (host) {
- silc_buffer_format(buf,
- SILC_STR_UI32_STRING(", "),
- SILC_STR_UI32_STRING("HN="),
- SILC_STR_UI32_STRING(host),
- SILC_STR_END);
- silc_buffer_pull(buf, 5 + strlen(host));
- tlen += 5 + strlen(host);
- }
-
- if (realname) {
- silc_buffer_format(buf,
- SILC_STR_UI32_STRING(", "),
- SILC_STR_UI32_STRING("RN="),
- SILC_STR_UI32_STRING(realname),
- SILC_STR_END);
- silc_buffer_pull(buf, 5 + strlen(realname));
- tlen += 5 + strlen(realname);
- }
-
- if (email) {
- silc_buffer_format(buf,
- SILC_STR_UI32_STRING(", "),
- SILC_STR_UI32_STRING("E="),
- SILC_STR_UI32_STRING(email),
- SILC_STR_END);
- silc_buffer_pull(buf, 4 + strlen(email));
- tlen += 4 + strlen(email);
- }
-
- if (org) {
- silc_buffer_format(buf,
- SILC_STR_UI32_STRING(", "),
- SILC_STR_UI32_STRING("O="),
- SILC_STR_UI32_STRING(org),
- SILC_STR_END);
- silc_buffer_pull(buf, 4 + strlen(org));
- tlen += 4 + strlen(org);
- }
-
- if (country) {
- silc_buffer_format(buf,
- SILC_STR_UI32_STRING(", "),
- SILC_STR_UI32_STRING("C="),
- SILC_STR_UI32_STRING(country),
- SILC_STR_END);
- silc_buffer_pull(buf, 4 + strlen(country));
- tlen += 4 + strlen(country);
- }
-
- silc_buffer_push(buf, buf->data - buf->head);
- identifier = silc_calloc(tlen + 1, sizeof(*identifier));
- memcpy(identifier, buf->data, tlen);
- silc_buffer_free(buf);
-
- return identifier;
+ return public_key->pkcs->public_key_bitlen(public_key->public_key);
}
-/* Decodes the provided `identifier' and returns allocated context for
- the identifier. */
+/* Returns internal PKCS public key context */
-SilcPublicKeyIdentifier silc_pkcs_decode_identifier(char *identifier)
+void *silc_pkcs_get_context(SilcPKCSType type, SilcPublicKey public_key)
{
- SilcPublicKeyIdentifier ident;
- char *cp, *item;
- int len;
-
- ident = silc_calloc(1, sizeof(*ident));
-
- cp = identifier;
- while (cp) {
- len = strcspn(cp, ",");
- if (len < 1) {
- cp = NULL;
- break;
- }
- if (len - 1 >= 0 && cp[len - 1] == '\\') {
- while (cp) {
- if (len + 1 > strlen(cp)) {
- cp = NULL;
- break;
- }
- cp += len + 1;
- len = strcspn(cp, ",") + len;
- if (len < 1) {
- cp = NULL;
- break;
- }
- if (len - 1 >= 0 && cp[len - 1] != '\\')
- break;
- }
- }
-
- if (!cp)
- break;
-
- item = silc_calloc(len + 1, sizeof(char));
- if (len > strlen(cp))
- break;
- memcpy(item, cp, len);
-
- if (strstr(item, "UN="))
- ident->username = strdup(item + strcspn(cp, "=") + 1);
- else if (strstr(item, "HN="))
- ident->host = strdup(item + strcspn(cp, "=") + 1);
- else if (strstr(item, "RN="))
- ident->realname = strdup(item + strcspn(cp, "=") + 1);
- else if (strstr(item, "E="))
- ident->email = strdup(item + strcspn(cp, "=") + 1);
- else if (strstr(item, "O="))
- ident->org = strdup(item + strcspn(cp, "=") + 1);
- else if (strstr(item, "C="))
- ident->country = strdup(item + strcspn(cp, "=") + 1);
-
- cp += len;
- if (strlen(cp) < 1)
- cp = NULL;
- else
- cp += 1;
-
- if (item)
- silc_free(item);
- }
-
- return ident;
+ if (public_key->pkcs->type != type)
+ return FALSE;
+ return public_key->public_key;
}
-/* Free's decoded public key identifier context. Call this to free the
- context returned by the silc_pkcs_decode_identifier. */
-void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier)
-{
- silc_free(identifier->username);
- silc_free(identifier->host);
- silc_free(identifier->realname);
- silc_free(identifier->email);
- silc_free(identifier->org);
- silc_free(identifier->country);
- silc_free(identifier);
-}
+/* Allocates new private key from key data */
-/* Allocates SILC style public key formed from sent arguments. All data
- is duplicated. */
-
-SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
- const char *identifier,
- const unsigned char *pk,
- SilcUInt32 pk_len)
+SilcBool silc_pkcs_private_key_alloc(SilcPKCSType type,
+ unsigned char *key,
+ SilcUInt32 key_len,
+ SilcPrivateKey *ret_private_key)
{
- SilcPublicKey public_key;
- char *tmp = NULL;
-
- public_key = silc_calloc(1, sizeof(*public_key));
- public_key->name = strdup(name);
- public_key->pk_len = pk_len;
- public_key->pk = silc_memdup(pk, pk_len);
- public_key->pk_type = SILC_SKE_PK_TYPE_SILC;
-
- if (!silc_utf8_valid(identifier, strlen(identifier))) {
- int len = silc_utf8_encoded_len(identifier, strlen(identifier), 0);
- tmp = silc_calloc(len + 1, sizeof(*tmp));
- silc_utf8_encode(identifier, strlen(identifier), 0, tmp, len);
- identifier = tmp;
- }
-
- public_key->identifier = strdup(identifier);
- public_key->len = 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
- silc_free(tmp);
+ const SilcPKCSObject *pkcs;
+ SilcPrivateKey private_key;
- return public_key;
-}
+ if (!ret_private_key)
+ return FALSE;
-/* Free's public key */
+ /* Allocate private key context */
+ private_key = silc_calloc(1, sizeof(*private_key));
+ if (!private_key)
+ return FALSE;
-void silc_pkcs_public_key_free(SilcPublicKey public_key)
-{
- if (public_key) {
- silc_free(public_key->name);
- silc_free(public_key->identifier);
- silc_free(public_key->pk);
- silc_free(public_key);
+ private_key->pkcs = pkcs = silc_pkcs_find_pkcs(type);
+ if (!private_key->pkcs) {
+ silc_free(private_key);
+ return FALSE;
}
-}
-/* Allocates SILC private key formed from sent arguments. All data is
- duplicated. */
-
-SilcPrivateKey silc_pkcs_private_key_alloc(const char *name,
- const unsigned char *prv,
- SilcUInt32 prv_len)
-{
- SilcPrivateKey private_key;
+ /* Import the PKCS private key */
+ if (!pkcs->import_private_key(key, key_len, &private_key->private_key)) {
+ silc_free(private_key);
+ return FALSE;
+ }
- private_key = silc_calloc(1, sizeof(*private_key));
- private_key->name = strdup(name);
- private_key->prv_len = prv_len;
- private_key->prv = silc_memdup(prv, prv_len);
+ *ret_private_key = private_key;
- return private_key;
+ return TRUE;
}
-/* Free's private key */
+/* Return key length */
-void silc_pkcs_private_key_free(SilcPrivateKey private_key)
+SilcUInt32 silc_pkcs_private_key_get_len(SilcPrivateKey private_key)
{
- if (private_key) {
- silc_free(private_key->name);
- if (private_key->prv) {
- memset(private_key->prv, 0, private_key->prv_len);
- silc_free(private_key->prv);
- }
- silc_free(private_key);
- }
+ return private_key->pkcs->private_key_bitlen(private_key->private_key);
}
-/* Encodes SILC style public key from SilcPublicKey. Returns the encoded
- data. */
+/* Frees the private key */
-unsigned char *
-silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len)
+void silc_pkcs_private_key_free(SilcPrivateKey private_key)
{
- return silc_pkcs_public_key_data_encode(public_key->pk,
- public_key->pk_len,
- public_key->name,
- public_key->identifier, len);
+ private_key->pkcs->private_key_free(private_key->private_key);
}
-/* Encodes SILC style public key. Returns the encoded data. */
+/* Encrypts */
-unsigned char *
-silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
- char *pkcs, char *identifier,
- SilcUInt32 *len)
+SilcBool silc_pkcs_encrypt(SilcPublicKey public_key,
+ unsigned char *src, SilcUInt32 src_len,
+ unsigned char *dst, SilcUInt32 dst_size,
+ SilcUInt32 *dst_len)
{
- SilcBuffer buf;
- unsigned char *ret;
- SilcUInt32 totlen;
-
- totlen = 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
- buf = silc_buffer_alloc_size(totlen + 4);
- if (!buf)
- return NULL;
-
- silc_buffer_format(buf,
- SILC_STR_UI_INT(totlen),
- SILC_STR_UI_SHORT(strlen(pkcs)),
- SILC_STR_UI32_STRING(pkcs),
- SILC_STR_UI_SHORT(strlen(identifier)),
- SILC_STR_UI32_STRING(identifier),
- SILC_STR_UI_XNSTRING(pk, pk_len),
- SILC_STR_END);
-
- ret = silc_buffer_steal(buf, len);
- silc_buffer_free(buf);
- return ret;
+ return public_key->pkcs->encrypt(public_key->public_key, src, src_len,
+ dst, dst_size, dst_len);
}
-/* Decodes SILC style public key. Returns TRUE if the decoding was
- successful. Allocates new public key as well. */
+/* Decrypts */
-SilcBool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
- SilcPublicKey *public_key)
+SilcBool silc_pkcs_decrypt(SilcPrivateKey private_key,
+ unsigned char *src, SilcUInt32 src_len,
+ unsigned char *dst, SilcUInt32 dst_size,
+ SilcUInt32 *dst_len)
{
- SilcBufferStruct buf;
- SilcPKCS alg;
- SilcUInt16 pkcs_len, identifier_len;
- SilcUInt32 totlen, key_len;
- unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
- int ret;
-
- silc_buffer_set(&buf, data, data_len);
-
- /* Get length */
- ret = silc_buffer_unformat(&buf,
- SILC_STR_UI_INT(&totlen),
- SILC_STR_END);
- if (ret == -1)
- return FALSE;
-
-#if 1 /* Backwards support, remove! */
- if (totlen == data_len)
- totlen -= 4;
-#endif
-
- if (totlen + 4 != data_len)
- return FALSE;
-
- /* Get algorithm name and identifier */
- silc_buffer_pull(&buf, 4);
- ret =
- silc_buffer_unformat(&buf,
- SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
- SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
- SILC_STR_END);
- if (ret == -1)
- goto err;
-
- if (pkcs_len < 1 || identifier_len < 3 ||
- pkcs_len + identifier_len > totlen)
- goto err;
-
- /* See if we support this algorithm (check only if PKCS are registered) */
- if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
- SILC_LOG_DEBUG(("Unknown PKCS %s", pkcs_name));
- goto err;
- }
-
- /* Protocol says that at least UN and HN must be provided as identifier,
- check for these. */
- if (!strstr(ident, "UN=") && !strstr(ident, "HN=")) {
- SILC_LOG_DEBUG(("The public does not have the required UN= and HN= "
- "identifiers"));
- goto err;
- }
-
- /* Get key data. We assume that rest of the buffer is key data. */
- silc_buffer_pull(&buf, 2 + pkcs_len + 2 + identifier_len);
- key_len = silc_buffer_len(&buf);
- ret = silc_buffer_unformat(&buf,
- SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
- SILC_STR_END);
- if (ret == -1)
- goto err;
-
- /* Try to set the key. If this fails the key must be malformed. This
- code assumes that the PKCS routine checks the format of the key.
- (check only if PKCS are registered) */
- if (SILC_PKCS_LIST) {
- silc_pkcs_alloc(pkcs_name, SILC_PKCS_SILC, &alg);
- if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
- goto err;
- silc_pkcs_free(alg);
- }
-
- if (public_key) {
- *public_key = silc_calloc(1, sizeof(**public_key));
- (*public_key)->len = totlen;
- (*public_key)->name = pkcs_name;
- (*public_key)->identifier = ident;
- (*public_key)->pk = key_data;
- (*public_key)->pk_len = key_len;
- (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
- }
-
- return TRUE;
-
- err:
- silc_free(pkcs_name);
- silc_free(ident);
- silc_free(key_data);
- return FALSE;
+ return private_key->pkcs->decrypt(private_key->private_key, src, src_len,
+ dst, dst_size, dst_len);
}
-/* Encodes Public Key Payload for transmitting public keys and certificates. */
+/* Generates signature */
-SilcBuffer silc_pkcs_public_key_payload_encode(SilcPublicKey public_key)
+SilcBool silc_pkcs_sign(SilcPrivateKey private_key,
+ unsigned char *src, SilcUInt32 src_len,
+ unsigned char *dst, SilcUInt32 dst_size,
+ SilcUInt32 *dst_len, SilcHash hash)
{
- SilcBuffer buffer;
- unsigned char *pk;
- SilcUInt32 pk_len;
-
- if (!public_key)
- return NULL;
-
- pk = silc_pkcs_public_key_encode(public_key, &pk_len);
- if (!pk)
- return NULL;
-
- buffer = silc_buffer_alloc_size(4 + pk_len);
- if (!buffer) {
- silc_free(pk);
- return NULL;
- }
-
- silc_buffer_format(buffer,
- SILC_STR_UI_SHORT(pk_len),
- SILC_STR_UI_SHORT(public_key->pk_type),
- SILC_STR_UI_XNSTRING(pk, pk_len),
- SILC_STR_END);
-
- silc_free(pk);
- return buffer;
+ return private_key->pkcs->sign(private_key->private_key, src, src_len,
+ dst, dst_size, dst_len, hash);
}
-/* Decode Public Key Payload and decodes the public key inside it to
- to `payload'. */
+/* Verifies signature */
-SilcBool silc_pkcs_public_key_payload_decode(unsigned char *data,
- SilcUInt32 data_len,
- SilcPublicKey *public_key)
+SilcBool silc_pkcs_verify(SilcPublicKey public_key,
+ unsigned char *signature,
+ SilcUInt32 signature_len,
+ unsigned char *data,
+ SilcUInt32 data_len, SilcHash hash)
{
- SilcBufferStruct buf;
- SilcUInt16 pk_len, pk_type;
- unsigned char *pk;
- int ret;
-
- if (!public_key)
- return FALSE;
-
- silc_buffer_set(&buf, data, data_len);
- ret = silc_buffer_unformat(&buf,
- SILC_STR_UI_SHORT(&pk_len),
- SILC_STR_UI_SHORT(&pk_type),
- SILC_STR_END);
- if (ret < 0 || pk_len > data_len - 4)
- return FALSE;
-
- /* For now we support only SILC public keys */
- if (pk_type != SILC_SKE_PK_TYPE_SILC)
- return FALSE;
-
- silc_buffer_pull(&buf, 4);
- ret = silc_buffer_unformat(&buf,
- SILC_STR_UI_XNSTRING(&pk, pk_len),
- SILC_STR_END);
- silc_buffer_push(&buf, 4);
- if (ret < 0)
- return FALSE;
-
- if (!silc_pkcs_public_key_decode(pk, pk_len, public_key))
- return FALSE;
- (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
-
- return TRUE;
+ return public_key->pkcs->verify(public_key->public_key, signature,
+ signature_len, data, data_len, hash);
}
/* Compares two public keys and returns TRUE if they are same key, and
SilcBool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2)
{
- if (key1 == key2)
- return TRUE;
-
- if (key1->len == key2->len &&
- key1->name && key2->name && key1->identifier && key2->identifier &&
- !strcmp(key1->name, key2->name) &&
- !strcmp(key1->identifier, key2->identifier) &&
- !memcmp(key1->pk, key2->pk, key1->pk_len) &&
- key1->pk_len == key2->pk_len)
- return TRUE;
+ if (key1->pkcs->type != key2->pkcs->type)
+ return FALSE;
- return FALSE;
+ return key1->pkcs->public_key_compare(key1->public_key, key2->public_key);
}
/* Copies the public key indicated by `public_key' and returns new allocated
if (!key)
return NULL;
- key->len = public_key->len;
- key->name = silc_memdup(public_key->name, strlen(public_key->name));
- key->identifier = silc_memdup(public_key->identifier,
- strlen(public_key->identifier));
- key->pk = silc_memdup(public_key->pk, public_key->pk_len);
- key->pk_len = public_key->pk_len;
- key->pk_type = public_key->pk_type;
+ key->pkcs = public_key->pkcs;
+ key->public_key = public_key->pkcs->public_key_copy(public_key->public_key);
+ if (!key->public_key) {
+ silc_free(key);
+ return NULL;
+ }
return key;
}
-/* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
-
-unsigned char *
-silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
-{
- return silc_pkcs_private_key_data_encode(private_key->prv,
- private_key->prv_len,
- private_key->name, len);
-}
-
-/* Encodes SILC private key. Returns the encoded data. */
+/* Loads any kind of public key */
-unsigned char *
-silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
- char *pkcs, SilcUInt32 *len)
+SilcBool silc_pkcs_load_public_key(const char *filename,
+ SilcPublicKey *ret_public_key)
{
- SilcBuffer buf;
- unsigned char *ret;
- SilcUInt32 totlen;
-
- totlen = 2 + strlen(pkcs) + prv_len;
- buf = silc_buffer_alloc_size(totlen);
- if (!buf)
- return NULL;
-
- silc_buffer_format(buf,
- SILC_STR_UI_SHORT(strlen(pkcs)),
- SILC_STR_UI32_STRING(pkcs),
- SILC_STR_UI_XNSTRING(prv, prv_len),
- SILC_STR_END);
+ unsigned char *data;
+ SilcUInt32 data_len;
+ SilcPublicKey public_key;
+ SilcPKCSType type;
- ret = silc_buffer_steal(buf, len);
- silc_buffer_free(buf);
- return ret;
-}
+ SILC_LOG_DEBUG(("Loading public key file '%s'", filename));
-/* Decodes SILC style private key. Returns TRUE if the decoding was
- successful. Allocates new private key as well. */
+ if (!ret_public_key)
+ return FALSE;
-SilcBool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
- SilcPrivateKey *private_key)
-{
- SilcBufferStruct buf;
- SilcPKCS alg;
- SilcUInt16 pkcs_len;
- SilcUInt32 key_len;
- unsigned char *pkcs_name = NULL, *key_data = NULL;
- int ret;
-
- silc_buffer_set(&buf, data, data_len);
-
- /* Get algorithm name and identifier */
- ret =
- silc_buffer_unformat(&buf,
- SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
- SILC_STR_END);
- if (ret == -1) {
- SILC_LOG_DEBUG(("Cannot decode private key buffer"));
- goto err;
- }
+ data = silc_file_readfile(filename, &data_len);
+ if (!data)
+ return FALSE;
- if (pkcs_len < 1 || pkcs_len > silc_buffer_truelen(&buf)) {
- SILC_LOG_DEBUG(("Malformed private key buffer"));
- goto err;
+ /* Allocate public key context */
+ *ret_public_key = public_key = silc_calloc(1, sizeof(*public_key));
+ if (!public_key) {
+ silc_free(data);
+ return FALSE;
}
- /* See if we support this algorithm (check only if PKCS are registered). */
- if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
- SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
- goto err;
- }
+ /* Try loading all types until one succeeds. */
+ for (type = SILC_PKCS_SILC; type <= SILC_PKCS_SPKI; type++) {
+ public_key->pkcs = silc_pkcs_find_pkcs(type);
+ if (!public_key->pkcs)
+ continue;
- /* Get key data. We assume that rest of the buffer is key data. */
- silc_buffer_pull(&buf, 2 + pkcs_len);
- key_len = silc_buffer_len(&buf);
- ret = silc_buffer_unformat(&buf,
- SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
- SILC_STR_END);
- if (ret == -1)
- goto err;
-
- /* Try to set the key. If this fails the key must be malformed. This
- code assumes that the PKCS routine checks the format of the key.
- (check only if PKCS are registered) */
- if (SILC_PKCS_LIST) {
- silc_pkcs_alloc(pkcs_name, SILC_PKCS_SILC, &alg);
- if (!alg->pkcs->set_private_key(alg->context, key_data, key_len)) {
- SILC_LOG_DEBUG(("Could not set private key data"));
- goto err;
- }
- silc_pkcs_free(alg);
- }
+ if (public_key->pkcs->import_public_key_file(data, data_len,
+ SILC_PKCS_FILE_BASE64,
+ &public_key->public_key))
+ return TRUE;
- if (private_key) {
- *private_key = silc_calloc(1, sizeof(**private_key));
- (*private_key)->name = pkcs_name;
- (*private_key)->prv = key_data;
- (*private_key)->prv_len = key_len;
+ if (public_key->pkcs->import_public_key_file(data, data_len,
+ SILC_PKCS_FILE_BIN,
+ &public_key->public_key))
+ return TRUE;
}
- return TRUE;
-
- err:
- silc_free(pkcs_name);
- silc_free(key_data);
+ silc_free(data);
+ silc_free(public_key);
return FALSE;
}
-/* Internal routine to save public key */
+/* Saves public key into a file */
-static SilcBool silc_pkcs_save_public_key_internal(const char *filename,
- unsigned char *data,
- SilcUInt32 data_len,
- SilcUInt32 encoding)
+SilcBool silc_pkcs_save_public_key(const char *filename,
+ SilcPublicKey public_key,
+ SilcPKCSFileEncoding encoding)
{
- SilcBuffer buf;
- SilcUInt32 len;
- unsigned char *tmp = NULL;
-
- switch(encoding) {
- case SILC_PKCS_FILE_BIN:
- break;
- case SILC_PKCS_FILE_PEM:
- tmp = data = silc_pem_encode_file(data, data_len);
- data_len = strlen(data);
- break;
- }
+ unsigned char *data;
+ SilcUInt32 data_len;
- len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
- strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
- buf = silc_buffer_alloc_size(len);
- if (!buf) {
- silc_free(tmp);
+ /* Export the public key file */
+ data = public_key->pkcs->export_public_key_file(public_key->public_key,
+ encoding, &data_len);
+ if (!data)
return FALSE;
- }
-
- silc_buffer_format(buf,
- SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
- SILC_STR_UI_XNSTRING(data, data_len),
- SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_END),
- SILC_STR_END);
- /* Save into file */
- if (silc_file_writefile(filename, buf->data, silc_buffer_len(buf))) {
- silc_free(tmp);
- silc_buffer_free(buf);
+ /* Write to file */
+ if (silc_file_writefile(filename, data, data_len)) {
+ silc_free(data);
return FALSE;
}
- silc_free(tmp);
- silc_buffer_free(buf);
+ silc_free(data);
return TRUE;
}
-/* Saves public key into file */
+/* Loads any kind of private key */
-SilcBool silc_pkcs_save_public_key(const char *filename, SilcPublicKey public_key,
- SilcUInt32 encoding)
+SilcBool silc_pkcs_load_private_key(const char *filename,
+ const unsigned char *passphrase,
+ SilcUInt32 passphrase_len,
+ SilcPrivateKey *ret_private_key)
{
unsigned char *data;
SilcUInt32 data_len;
- SilcBool ret;
-
- data = silc_pkcs_public_key_encode(public_key, &data_len);
- ret = silc_pkcs_save_public_key_internal(filename, data, data_len,
- encoding);
- silc_free(data);
- return ret;
-}
-
-/* Saves public key into file */
-
-SilcBool silc_pkcs_save_public_key_data(const char *filename, unsigned char *data,
- SilcUInt32 data_len, SilcUInt32 encoding)
-{
- return silc_pkcs_save_public_key_internal(filename, data, data_len,
- encoding);
-}
-
-#define SILC_PKCS_PRIVATE_KEY_MAGIC 0x738df531
-
-/* Internal routine to save private key. */
-
-static SilcBool silc_pkcs_save_private_key_internal(const char *filename,
- unsigned char *data,
- SilcUInt32 data_len,
- unsigned char *key,
- SilcUInt32 key_len,
- SilcUInt32 encoding)
-{
- SilcCipher aes;
- SilcHash sha1;
- SilcHmac sha1hmac;
- SilcBuffer buf, enc;
- SilcUInt32 len, blocklen, padlen;
- unsigned char tmp[32], keymat[64];
- int i;
+ SilcPrivateKey private_key;
+ SilcPKCSType type;
- memset(tmp, 0, sizeof(tmp));
- memset(keymat, 0, sizeof(keymat));
+ SILC_LOG_DEBUG(("Loading private key file '%s'", filename));
- /* Allocate the AES cipher */
- if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
- SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
- return FALSE;
- }
- blocklen = silc_cipher_get_block_len(aes);
- if (blocklen * 2 > sizeof(tmp))
+ if (!ret_private_key)
return FALSE;
- /* Allocate SHA1 hash */
- if (!silc_hash_alloc("sha1", &sha1)) {
- SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
- silc_cipher_free(aes);
+ data = silc_file_readfile(filename, &data_len);
+ if (!data)
return FALSE;
- }
- /* Allocate HMAC */
- if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
- SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
- silc_hash_free(sha1);
- silc_cipher_free(aes);
+ /* Allocate private key context */
+ *ret_private_key = private_key = silc_calloc(1, sizeof(*private_key));
+ if (!private_key) {
+ silc_free(data);
return FALSE;
}
- /* Derive the encryption key from the provided key material. The key
- is 256 bits length, and derived by taking hash of the data, then
- re-hashing the data and the previous digest, and using the first and
- second digest as the key. */
- silc_hash_init(sha1);
- silc_hash_update(sha1, key, key_len);
- silc_hash_final(sha1, keymat);
- silc_hash_init(sha1);
- silc_hash_update(sha1, key, key_len);
- silc_hash_update(sha1, keymat, 16);
- silc_hash_final(sha1, keymat + 16);
-
- /* Set the key to the cipher */
- silc_cipher_set_key(aes, keymat, 256);
-
- /* Encode the buffer to be encrypted. Add padding to it too, at least
- block size of the cipher. */
-
- /* Allocate buffer for encryption */
- len = silc_hmac_len(sha1hmac);
- padlen = 16 + (16 - ((data_len + 4) % blocklen));
- enc = silc_buffer_alloc_size(4 + 4 + data_len + padlen + len);
- if (!enc) {
- silc_hmac_free(sha1hmac);
- silc_hash_free(sha1);
- silc_cipher_free(aes);
- return FALSE;
- }
+ /* Try loading all types until one succeeds. */
+ for (type = SILC_PKCS_SILC; type <= SILC_PKCS_SPKI; type++) {
+ private_key->pkcs = silc_pkcs_find_pkcs(type);
+ if (!private_key->pkcs)
+ continue;
- /* Generate padding */
- for (i = 0; i < padlen; i++)
- tmp[i] = silc_rng_global_get_byte_fast();
-
- /* Put magic number */
- SILC_PUT32_MSB(SILC_PKCS_PRIVATE_KEY_MAGIC, enc->data);
- silc_buffer_pull(enc, 4);
-
- /* Encode the buffer */
- silc_buffer_format(enc,
- SILC_STR_UI_INT(data_len),
- SILC_STR_UI_XNSTRING(data, data_len),
- SILC_STR_UI_XNSTRING(tmp, padlen),
- SILC_STR_END);
-
- /* Encrypt. */
- silc_cipher_encrypt(aes, enc->data, enc->data, silc_buffer_len(enc) - len,
- silc_cipher_get_iv(aes));
-
- silc_buffer_push(enc, 4);
-
- /* Compute HMAC over the encrypted data and append the MAC to data.
- The key is the first digest of the original key material. */
- data_len = silc_buffer_len(enc) - len;
- silc_hmac_init_with_key(sha1hmac, keymat, 16);
- silc_hmac_update(sha1hmac, enc->data, data_len);
- silc_buffer_pull(enc, data_len);
- silc_hmac_final(sha1hmac, enc->data, NULL);
- silc_buffer_push(enc, data_len);
-
- /* Cleanup */
- memset(keymat, 0, sizeof(keymat));
- memset(tmp, 0, sizeof(tmp));
- silc_hmac_free(sha1hmac);
- silc_hash_free(sha1);
- silc_cipher_free(aes);
-
- data = enc->data;
- data_len = silc_buffer_len(enc);
-
- switch (encoding) {
- case SILC_PKCS_FILE_BIN:
- break;
- case SILC_PKCS_FILE_PEM:
- data = silc_pem_encode_file(data, data_len);
- data_len = strlen(data);
- break;
- }
+ if (private_key->pkcs->import_private_key_file(data, data_len,
+ passphrase,
+ passphrase_len,
+ SILC_PKCS_FILE_BIN,
+ &private_key->private_key))
+ return TRUE;
- /* Encode the data and save to file */
- len = data_len + (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
- strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
- buf = silc_buffer_alloc_size(len);
- silc_buffer_format(buf,
- SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_BEGIN),
- SILC_STR_UI_XNSTRING(data, data_len),
- SILC_STR_UI32_STRING(SILC_PKCS_PRIVATE_KEYFILE_END),
- SILC_STR_END);
-
- /* Save into a file */
- if (silc_file_writefile_mode(filename, buf->data,
- silc_buffer_len(buf), 0600)) {
- silc_buffer_clear(buf);
- silc_buffer_free(buf);
- silc_buffer_clear(enc);
- silc_buffer_free(enc);
- return FALSE;
+ if (private_key->pkcs->import_private_key_file(data, data_len,
+ passphrase,
+ passphrase_len,
+ SILC_PKCS_FILE_BASE64,
+ &private_key->private_key))
+ return TRUE;
}
- silc_buffer_clear(buf);
- silc_buffer_free(buf);
- silc_buffer_clear(enc);
- silc_buffer_free(enc);
- return TRUE;
+ silc_free(data);
+ silc_free(private_key);
+ return FALSE;
}
-/* Saves private key into file. */
+/* Saves private key into a file */
SilcBool silc_pkcs_save_private_key(const char *filename,
- SilcPrivateKey private_key,
- unsigned char *passphrase,
- SilcUInt32 passphrase_len,
- SilcUInt32 encoding)
+ SilcPrivateKey private_key,
+ const unsigned char *passphrase,
+ SilcUInt32 passphrase_len,
+ SilcPKCSFileEncoding encoding,
+ SilcRng rng)
{
unsigned char *data;
SilcUInt32 data_len;
- SilcBool ret;
-
- data = silc_pkcs_private_key_encode(private_key, &data_len);
- ret = silc_pkcs_save_private_key_internal(filename, data, data_len,
- passphrase, passphrase_len,
- encoding);
- memset(data, 0, data_len);
- silc_free(data);
- return ret;
-}
-
-/* Loads public key from file and allocates new public key. Returns TRUE
- if loading was successful. */
-
-SilcBool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key,
- SilcUInt32 encoding)
-{
- unsigned char *cp, *old, *data, byte;
- SilcUInt32 i, data_len, len;
-
- SILC_LOG_DEBUG(("Loading public key `%s' with %s encoding", filename,
- encoding == SILC_PKCS_FILE_PEM ? "Base64" :
- encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
- old = data = silc_file_readfile(filename, &data_len);
+ /* Export the private key file */
+ data = private_key->pkcs->export_private_key_file(private_key->private_key,
+ passphrase,
+ passphrase_len,
+ encoding, rng, &data_len);
if (!data)
return FALSE;
- /* Check start of file and remove header from the data. */
- len = strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN);
- cp = data;
- for (i = 0; i < len; i++) {
- byte = cp[0];
- cp++;
- if (byte != SILC_PKCS_PUBLIC_KEYFILE_BEGIN[i]) {
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
- }
- data = cp;
-
- /* Decode public key */
- if (public_key) {
- len = data_len - (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
- strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
-
- switch(encoding) {
- case SILC_PKCS_FILE_BIN:
- break;
- case SILC_PKCS_FILE_PEM:
- data = silc_pem_decode(data, len, &len);
- memset(old, 0, data_len);
- silc_free(old);
- old = data;
- data_len = len;
- break;
- }
-
- if (!data || !silc_pkcs_public_key_decode(data, len, public_key)) {
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
- }
-
- memset(old, 0, data_len);
- silc_free(old);
- return TRUE;
-}
-
-/* Load private key from file and allocates new private key. Returns TRUE
- if loading was successful. */
-
-SilcBool silc_pkcs_load_private_key(const char *filename,
- SilcPrivateKey *private_key,
- unsigned char *passphrase,
- SilcUInt32 passphrase_len,
- SilcUInt32 encoding)
-{
- SilcCipher aes;
- SilcHash sha1;
- SilcHmac sha1hmac;
- SilcUInt32 blocklen;
- unsigned char tmp[32], keymat[64];
- unsigned char *cp, *old, *data, byte;
- SilcUInt32 i, data_len, len, magic, mac_len;
-
- SILC_LOG_DEBUG(("Loading private key `%s' with %s encoding", filename,
- encoding == SILC_PKCS_FILE_PEM ? "Base64" :
- encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
-
- old = data = silc_file_readfile(filename, &data_len);
- if (!data)
+ /* Write to file */
+ if (silc_file_writefile(filename, data, data_len)) {
+ silc_free(data);
return FALSE;
-
- /* Check start of file and remove header from the data. */
- len = strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN);
- cp = data;
- for (i = 0; i < len; i++) {
- byte = cp[0];
- cp++;
- if (byte != SILC_PKCS_PRIVATE_KEYFILE_BEGIN[i]) {
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
- }
- data = cp;
-
- /* Decode private key */
- len = data_len - (strlen(SILC_PKCS_PRIVATE_KEYFILE_BEGIN) +
- strlen(SILC_PKCS_PRIVATE_KEYFILE_END));
-
- switch(encoding) {
- case SILC_PKCS_FILE_BIN:
- break;
- case SILC_PKCS_FILE_PEM:
- data = silc_pem_decode(data, len, &len);
- if (!data) {
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
- break;
}
- memset(tmp, 0, sizeof(tmp));
- memset(keymat, 0, sizeof(keymat));
-
- /* Private key files without the specific magic number are assumed
- to be the old-style private keys that are not encrypted. */
- SILC_GET32_MSB(magic, data);
- if (magic != SILC_PKCS_PRIVATE_KEY_MAGIC) {
- SILC_LOG_DEBUG(("Private key does not have correct magic!"));
-
- /* Now decode the actual private key */
- if (!silc_pkcs_private_key_decode(data, len, private_key)) {
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
-
- memset(old, 0, data_len);
- silc_free(old);
- return TRUE;
- }
-
- /* Allocate the AES cipher */
- if (!silc_cipher_alloc("aes-256-cbc", &aes)) {
- SILC_LOG_ERROR(("Could not allocate AES cipher, probably not registered"));
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
- blocklen = silc_cipher_get_block_len(aes);
- if (blocklen * 2 > sizeof(tmp)) {
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
-
- /* Allocate SHA1 hash */
- if (!silc_hash_alloc("sha1", &sha1)) {
- SILC_LOG_ERROR(("Could not allocate SHA1 hash, probably not registered"));
- silc_cipher_free(aes);
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
-
- /* Allocate HMAC */
- if (!silc_hmac_alloc("hmac-sha1-96", NULL, &sha1hmac)) {
- SILC_LOG_ERROR(("Could not allocate SHA1 HMAC, probably not registered"));
- silc_hash_free(sha1);
- silc_cipher_free(aes);
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
-
- /* Derive the decryption key from the provided key material. The key
- is 256 bits length, and derived by taking hash of the data, then
- re-hashing the data and the previous digest, and using the first and
- second digest as the key. */
- silc_hash_init(sha1);
- silc_hash_update(sha1, passphrase, passphrase_len);
- silc_hash_final(sha1, keymat);
- silc_hash_init(sha1);
- silc_hash_update(sha1, passphrase, passphrase_len);
- silc_hash_update(sha1, keymat, 16);
- silc_hash_final(sha1, keymat + 16);
-
- /* Set the key to the cipher */
- silc_cipher_set_key(aes, keymat, 256);
-
- /* First, verify the MAC of the private key data */
- mac_len = silc_hmac_len(sha1hmac);
- silc_hmac_init_with_key(sha1hmac, keymat, 16);
- silc_hmac_update(sha1hmac, data, len - mac_len);
- silc_hmac_final(sha1hmac, tmp, NULL);
- if (memcmp(tmp, data + (len - mac_len), mac_len)) {
- SILC_LOG_DEBUG(("Integrity check for private key failed"));
- memset(keymat, 0, sizeof(keymat));
- memset(tmp, 0, sizeof(tmp));
- silc_hmac_free(sha1hmac);
- silc_hash_free(sha1);
- silc_cipher_free(aes);
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
- data += 4;
- len -= 4;
-
- /* Decrypt the private key buffer */
- silc_cipher_decrypt(aes, data, data, len - mac_len, NULL);
- SILC_GET32_MSB(i, data);
- if (i > len) {
- SILC_LOG_DEBUG(("Bad private key length in buffer!"));
- memset(keymat, 0, sizeof(keymat));
- memset(tmp, 0, sizeof(tmp));
- silc_hmac_free(sha1hmac);
- silc_hash_free(sha1);
- silc_cipher_free(aes);
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
- data += 4;
- len = i;
-
- /* Cleanup */
- memset(keymat, 0, sizeof(keymat));
- memset(tmp, 0, sizeof(tmp));
- silc_hmac_free(sha1hmac);
- silc_hash_free(sha1);
- silc_cipher_free(aes);
-
- /* Now decode the actual private key */
- if (!silc_pkcs_private_key_decode(data, len, private_key)) {
- memset(old, 0, data_len);
- silc_free(old);
- return FALSE;
- }
-
- memset(old, 0, data_len);
- silc_free(old);
+ silc_free(data);
return TRUE;
}
*/
-#ifndef SILCPKCS_H
-#define SILCPKCS_H
-
/****h* silccrypt/SILC PKCS Interface
*
* DESCRIPTION
*
- * This is the interface for public key cryptosystems, and various
- * utility functions related to public keys and private keys. This
- * interface also defines the actual PKCS objects, public keys and
- * private keys. The interface is generic PKCS interface, which has
- * capability of supporting any kind of public key algorithm. This
- * interface also implements the SILC Public Key and routines for
- * encoding and decoding SILC Public Key (as defined by the SILC
- * protocol specification). Interface or encrypting, decrypting,
- * producing digital signatures and verifying digital signatures are
- * also defined in this header.
+ * SILC PKCS API provides generic interface for performing various
+ * public key cryptography related operations with different types of
+ * public and private keys. Support for loading and saving of different
+ * types of public key and private keys are also provided.
*
***/
-/****s* silccrypt/SilcPKCSAPI/SilcPKCS
- *
- * NAME
- *
- * typedef struct SilcPKCSStruct *SilcPKCS;
- *
- * DESCRIPTION
- *
- * This context is the actual PKCS context and is allocated
- * by silc_pkcs_alloc and given as argument usually to all
- * silc_pkcs_* functions. It is freed by the silc_pkcs_free
- * function.
- *
- ***/
-typedef struct SilcPKCSStruct *SilcPKCS;
+#ifndef SILCPKCS_H
+#define SILCPKCS_H
+
+/* Forward declarations */
+typedef struct SilcPKCSObjectStruct SilcPKCSObject;
/****d* silccrypt/SilcPKCSAPI/SilcPKCSType
*
* NAME
*
- * typedef enum { ... } SilcPKCSType
+ * typedef enum { ... } SilcPKCSType;
*
* DESCRIPTION
*
* SOURCE
*/
typedef enum {
- SILC_PKCS_SILC = 1, /* SILC PKCS (mandatory) */
+ SILC_PKCS_SILC = 1, /* SILC PKCS */
SILC_PKCS_SSH2 = 2, /* SSH2 PKCS (not supported) */
SILC_PKCS_X509V3 = 3, /* X.509v3 PKCS (not supported) */
SILC_PKCS_OPENPGP = 4, /* OpenPGP PKCS (not supported) */
} SilcPKCSType;
/***/
-/* The default SILC PKCS (Public Key Cryptosystem) object to represent
- any PKCS in SILC. */
-typedef struct SilcPKCSObjectStruct {
- char *name;
- SilcPKCSType type;
- int (*init)(void *, SilcUInt32, SilcRng);
- void (*clear_keys)(void *);
- unsigned char *(*get_public_key)(void *, SilcUInt32 *);
- unsigned char *(*get_private_key)(void *, SilcUInt32 *);
- SilcUInt32 (*set_public_key)(void *, unsigned char *, SilcUInt32);
- SilcUInt32 (*set_private_key)(void *, unsigned char *, SilcUInt32);
- SilcUInt32 (*context_len)();
- int (*encrypt)(void *, unsigned char *, SilcUInt32,
- unsigned char *, SilcUInt32 *);
- int (*decrypt)(void *, unsigned char *, SilcUInt32,
- unsigned char *, SilcUInt32 *);
- int (*sign)(void *, unsigned char *, SilcUInt32,
- unsigned char *, SilcUInt32 *);
- int (*verify)(void *, unsigned char *, SilcUInt32,
- unsigned char *, SilcUInt32);
-} SilcPKCSObject;
-
/****s* silccrypt/SilcPKCSAPI/SilcPublicKey
*
* NAME
*
- * typedef struct { ... } *SilcPublicKey, SilcPublicKeyStruct;
+ * typedef struct { ... } *SilcPublicKey;
*
* DESCRIPTION
*
- * SILC style public key object. Public key is read from file to this
- * object. Public keys received from network must be in this format as
- * well. The format is defined by the SILC protocol specification.
- * This object is allocated by silc_pkcs_public_key_alloc and freed
- * by silc_pkcs_public_key_free. The object is given as argument to
- * all silc_pkcs_public_key_* functions.
+ * This context represents any kind of PKCS public key. It can be
+ * allocated by silc_pkcs_public_key_alloc and is freed by the
+ * silc_pkcs_public_key_free. The PKCS specific public key context
+ * can be retrieved by calling silc_pkcs_get_context.
*
* SOURCE
*/
typedef struct {
- SilcUInt16 pk_type; /* Public key type (SilcSKEPKType) */
- SilcUInt32 len;
- char *name;
- char *identifier;
- unsigned char *pk;
- SilcUInt32 pk_len;
-} *SilcPublicKey, SilcPublicKeyStruct;
+ const SilcPKCSObject *pkcs; /* PKCS */
+ void *public_key; /* PKCS specific public key */
+} *SilcPublicKey;
/***/
-/****s* silccrypt/SilcPKCSAPI/SilcPublicKeyIdentifier
+/****s* silccrypt/SilcPKCSAPI/SilcPrivateKey
*
* NAME
*
- * typedef struct { ... } *SilcPublicKeyIdentifier,
- * SilcPublicKeyIdentifierStruct;
+ * typedef struct { ... } *SilcPrivateKey;
*
* DESCRIPTION
*
- * Decoded SILC Public Key identifier. Note that some of the fields
- * may be NULL. This context is allocated by the function
- * silc_pkcs_decode_identifier and freed by silc_pkcs_free_identifier.
- * The identifier in SilcPublicKey is the `identifier' field, which
- * can be given as argument to silc_pkcs_decode_identifier.
+ * This context represents any kind of PKCS private key.
*
* SOURCE
*/
typedef struct {
- char *username;
- char *host;
- char *realname;
- char *email;
- char *org;
- char *country;
-} *SilcPublicKeyIdentifier, SilcPublicKeyIdentifierStruct;
+ const SilcPKCSObject *pkcs; /* PKCS */
+ void *private_key; /* PKCS specific private key */
+} *SilcPrivateKey;
/***/
-/****s* silccrypt/SilcPKCSAPI/SilcPrivateKey
+/****d* silccrypt/SilcPKCSAPI/SilcPKCSFileEncoding
*
* NAME
*
- * typedef struct { ... } *SilcPrivateKey, SilcPrivateKeyStruct;
+ * typedef enum { ... } SilcPKCSType
*
* DESCRIPTION
*
- * SILC style private key object. Public key is read from file to this
- * object. This object is allocated by silc_pkcs_private_key_alloc and
- * freed by silc_pkcs_private_key_free. The object is given as argument
- * to all silc_pkcs_private_key_* functions.
+ * Public and private key file encoding types.
*
- ***/
+ * SOURCE
+ */
+typedef enum {
+ SILC_PKCS_FILE_BIN, /* Binary encoding */
+ SILC_PKCS_FILE_BASE64 /* Base64 encoding */
+} SilcPKCSFileEncoding;
+/***/
+
+/* The PKCS Algorithm object to represent any PKCS algorithm. */
typedef struct {
+ /* Algorithm name and scheme */
char *name;
- unsigned char *prv;
- SilcUInt32 prv_len;
-} *SilcPrivateKey, SilcPrivateKeyStruct;
-
-/* Public and private key file headers */
-#define SILC_PKCS_PUBLIC_KEYFILE_BEGIN "-----BEGIN SILC PUBLIC KEY-----\n"
-#define SILC_PKCS_PUBLIC_KEYFILE_END "\n-----END SILC PUBLIC KEY-----\n"
-#define SILC_PKCS_PRIVATE_KEYFILE_BEGIN "-----BEGIN SILC PRIVATE KEY-----\n"
-#define SILC_PKCS_PRIVATE_KEYFILE_END "\n-----END SILC PRIVATE KEY-----\n"
+ char *scheme;
+
+ /* Supported hash functions, comma separated list */
+ char *hash;
+
+ /* Generate new key pair. Returns PKCS algorithm specific public key
+ and private key contexts. */
+ SilcBool (*generate_key)(SilcUInt32 keylen,
+ SilcRng rng,
+ void **ret_public_key,
+ void **ret_private_key);
+
+ /* Public key routines */
+ SilcBool (*import_public_key)(unsigned char *key,
+ SilcUInt32 key_len,
+ void **ret_public_key);
+ unsigned char *(*export_public_key)(void *public_key,
+ SilcUInt32 *ret_len);
+ SilcUInt32 (*public_key_bitlen)(void *public_key);
+ void *(*public_key_copy)(void *public_key);
+ SilcBool (*public_key_compare)(void *key1, void *key2);
+ void (*public_key_free)(void *public_key);
+
+ /* Private key routines */
+ SilcBool (*import_private_key)(unsigned char *key,
+ SilcUInt32 key_len,
+ void **ret_private_key);
+ unsigned char *(*export_private_key)(void *private_key,
+ SilcUInt32 *ret_len);
+ SilcUInt32 (*private_key_bitlen)(void *public_key);
+ void (*private_key_free)(void *private_key);
+
+ /* Encrypt and decrypt operations */
+ SilcBool (*encrypt)(void *public_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *dst,
+ SilcUInt32 dst_size,
+ SilcUInt32 *ret_dst_len);
+ SilcBool (*decrypt)(void *private_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *dst,
+ SilcUInt32 dst_size,
+ SilcUInt32 *ret_dst_len);
+
+ /* Signature and verification operations */
+ SilcBool (*sign)(void *private_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *signature,
+ SilcUInt32 signature_size,
+ SilcUInt32 *ret_signature_len,
+ SilcHash hash);
+ SilcBool (*verify)(void *public_key,
+ unsigned char *signature,
+ SilcUInt32 signature_len,
+ unsigned char *data,
+ SilcUInt32 data_len,
+ SilcHash hash);
+} SilcPKCSAlgorithm;
+
+/* The PKCS (Public Key Cryptosystem) object to represent any PKCS. */
+struct SilcPKCSObjectStruct {
+ /* PKCS type */
+ SilcPKCSType type;
-/* Public and private key file encoding types */
-#define SILC_PKCS_FILE_BIN 0
-#define SILC_PKCS_FILE_PEM 1
+ /* Public key routines */
+
+ /* Returns PKCS algorithm context from public key */
+ const SilcPKCSAlgorithm *(*get_algorithm)(void *public_key);
+
+ /* Imports from public key file */
+ SilcBool (*import_public_key_file)(unsigned char *filedata,
+ SilcUInt32 filedata_len,
+ SilcPKCSFileEncoding encoding,
+ void **ret_public_key);
+
+ /* Imports from public key binary data */
+ SilcBool (*import_public_key)(unsigned char *key,
+ SilcUInt32 key_len,
+ void **ret_public_key);
+
+ /* Exports public key to file */
+ unsigned char *(*export_public_key_file)(void *public_key,
+ SilcPKCSFileEncoding encoding,
+ SilcUInt32 *ret_len);
+
+ /* Export public key as binary data */
+ unsigned char *(*export_public_key)(void *public_key,
+ SilcUInt32 *ret_len);
+
+ /* Returns key length in bits */
+ SilcUInt32 (*public_key_bitlen)(void *public_key);
+
+ /* Copy public key */
+ void *(*public_key_copy)(void *public_key);
+
+ /* Compares public keys */
+ SilcBool (*public_key_compare)(void *key1, void *key2);
+
+ /* Free public key */
+ void (*public_key_free)(void *public_key);
+
+ /* Private key routines */
+
+ /* Imports from private key file */
+ SilcBool (*import_private_key_file)(unsigned char *filedata,
+ SilcUInt32 filedata_len,
+ const char *passphrase,
+ SilcUInt32 passphrase_len,
+ SilcPKCSFileEncoding encoding,
+ void **ret_private_key);
+
+ /* Imports from private key binary data */
+ SilcBool (*import_private_key)(unsigned char *key,
+ SilcUInt32 key_len,
+ void **ret_private_key);
+
+ /* Exports private key to file */
+ unsigned char *(*export_private_key_file)(void *private_key,
+ const char *passphrase,
+ SilcUInt32 passphrase_len,
+ SilcPKCSFileEncoding encoding,
+ SilcRng rng,
+ SilcUInt32 *ret_len);
+
+ /* Export private key as binary data */
+ unsigned char *(*export_private_key)(void *private_key,
+ SilcUInt32 *ret_len);
+
+ /* Returns key length in bits */
+ SilcUInt32 (*private_key_bitlen)(void *private_key);
+
+ /* Free private key */
+ void (*private_key_free)(void *private_key);
+
+ /* Encrypt and decrypt operations */
+ SilcBool (*encrypt)(void *public_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *dst,
+ SilcUInt32 dst_size,
+ SilcUInt32 *ret_dst_len);
+ SilcBool (*decrypt)(void *private_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *dst,
+ SilcUInt32 dst_size,
+ SilcUInt32 *ret_dst_len);
+
+ /* Signature and verification operations */
+ SilcBool (*sign)(void *private_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *signature,
+ SilcUInt32 signature_size,
+ SilcUInt32 *ret_signature_len,
+ SilcHash hash);
+ SilcBool (*verify)(void *public_key,
+ unsigned char *signature,
+ SilcUInt32 signature_len,
+ unsigned char *data,
+ SilcUInt32 data_len,
+ SilcHash hash);
+};
/* Marks for all PKCS in silc. This can be used in silc_pkcs_unregister
to unregister all PKCS at once. */
#define SILC_ALL_PKCS ((SilcPKCSObject *)1)
+#define SILC_ALL_PKCS_ALG ((SilcPKCSAlgorithm *)1)
-/* Static list of PKCS for silc_pkcs_register_default(). */
+/* Static lists of PKCS and PKCS algorithms. */
extern DLLAPI const SilcPKCSObject silc_default_pkcs[];
-
-/* Default PKXS in the SILC protocol */
-#define SILC_DEFAULT_PKCS "rsa"
-
-/* Macros */
-
-/* Macros used to implement the SILC PKCS API */
-
-/* XXX: This needs slight redesigning. These needs to be made even
- more generic. I don't like that the actual prime generation is done
- in PKCS_API_INIT. The primes used in key generation should be sent
- as argument to the init function. By doing this we would achieve
- that PKCS could be used as SIM's. The only requirement would be
- that they are compiled against GMP (well, actually even that would
- not be a requirement, but the most generic case anyway). The new init
- would look something like this:
-
- #define SILC_PKCS_API_INIT(pkcs) \
- inline int silc_##pkcs##_init(void *context, SilcUInt32 keylen, \
- void *p1, void *p2)
-
- Now we wouldn't have to send the SilcRng object since the primes are
- provided as arguments. To send them as void * they could actually be
- used as in anyway for real (MP_INT (SilcMPInt) or even something else
- (the pointer could be kludged to be something else in the module))
- (Plus, the SilcRng object management in prime generation would be
- simpler and better what it is now (in silcprimegen.c, that is)).
-*/
-
-#define SILC_PKCS_API_INIT(pkcs) \
-int silc_##pkcs##_init(void *context, SilcUInt32 keylen, \
- SilcRng rng)
-#define SILC_PKCS_API_CLEAR_KEYS(pkcs) \
-void silc_##pkcs##_clear_keys(void *context)
-#define SILC_PKCS_API_GET_PUBLIC_KEY(pkcs) \
-unsigned char *silc_##pkcs##_get_public_key(void *context, \
- SilcUInt32 *ret_len)
-#define SILC_PKCS_API_GET_PRIVATE_KEY(pkcs) \
-unsigned char *silc_##pkcs##_get_private_key(void *context, \
- SilcUInt32 *ret_len)
-#define SILC_PKCS_API_SET_PUBLIC_KEY(pkcs) \
-SilcUInt32 silc_##pkcs##_set_public_key(void *context, unsigned char *key_data, \
- SilcUInt32 key_len)
-#define SILC_PKCS_API_SET_PRIVATE_KEY(pkcs) \
-SilcUInt32 silc_##pkcs##_set_private_key(void *context, unsigned char *key_data, \
- SilcUInt32 key_len)
-#define SILC_PKCS_API_CONTEXT_LEN(pkcs) \
-SilcUInt32 silc_##pkcs##_context_len()
-#define SILC_PKCS_API_ENCRYPT(pkcs) \
-int silc_##pkcs##_encrypt(void *context, \
- unsigned char *src, \
- SilcUInt32 src_len, \
- unsigned char *dst, \
- SilcUInt32 *dst_len)
-#define SILC_PKCS_API_DECRYPT(pkcs) \
-int silc_##pkcs##_decrypt(void *context, \
- unsigned char *src, \
- SilcUInt32 src_len, \
- unsigned char *dst, \
- SilcUInt32 *dst_len)
-#define SILC_PKCS_API_SIGN(pkcs) \
-int silc_##pkcs##_sign(void *context, \
- unsigned char *src, \
- SilcUInt32 src_len, \
- unsigned char *dst, \
- SilcUInt32 *dst_len)
-#define SILC_PKCS_API_VERIFY(pkcs) \
-int silc_##pkcs##_verify(void *context, \
- unsigned char *signature, \
- SilcUInt32 signature_len, \
- unsigned char *data, \
- SilcUInt32 data_len)
+extern DLLAPI const SilcPKCSAlgorithm silc_default_pkcs_alg[];
/* Prototypes */
***/
SilcBool silc_pkcs_unregister(SilcPKCSObject *pkcs);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_register_default
- *
- * SYNOPSIS
- *
- * SilcBool silc_pkcs_register_default(void);
- *
- * DESCRIPTION
- *
- * Registers all the default PKCS (all builtin PKCS). The application may
- * use this to register the default PKCS if specific PKCS in any specific
- * order is not wanted. Returns FALSE on error.
- *
- ***/
-SilcBool silc_pkcs_register_default(void);
-
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_unregister_all
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_algorithm_register
*
* SYNOPSIS
*
- * SilcBool silc_pkcs_unregister_all(void);
+ * SilcBool silc_pkcs_algorithm_register(const SilcPKCSAlgorithm *pkcs);
*
* DESCRIPTION
*
- * Returns FALSE on error.
+ * Registers a new PKCS Algorithm into the SILC. This function is used
+ * at the initialization of the SILC. All registered PKCS algorithms
+ * should be unregistered with silc_pkcs_unregister.
*
***/
-SilcBool silc_pkcs_unregister_all(void);
+SilcBool silc_pkcs_algorithm_register(const SilcPKCSAlgorithm *pkcs);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_alloc
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_algorithm_unregister
*
* SYNOPSIS
*
- * SilcBool silc_pkcs_alloc(const unsigned char *name,
- * SilcPKCSType type, SilcPKCS *new_pkcs);
+ * SilcBool silc_pkcs_algorithm_unregister(SilcPKCSAlgorithm *pkcs);
*
* DESCRIPTION
*
- * Allocates a new SilcPKCS object. The new allocated object is returned
- * to the 'new_pkcs' argument. Returns FALSE on error.
+ * Unregister a PKCS from the SILC. Returns FALSE on error.
*
***/
-SilcBool silc_pkcs_alloc(const unsigned char *name,
- SilcPKCSType type, SilcPKCS *new_pkcs);
+SilcBool silc_pkcs_algorithm_unregister(SilcPKCSAlgorithm *pkcs);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_free
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_register_default
*
* SYNOPSIS
*
- * void silc_pkcs_free(SilcPKCS pkcs);
+ * SilcBool silc_pkcs_register_default(void);
*
* DESCRIPTION
*
- * Frees the PKCS object.
+ * Registers all the default PKCS (all builtin PKCS) and PKCS algorithms.
+ * The application may use this to register the default PKCS if specific
+ * PKCS in any specific order is not wanted. Returns FALSE on error.
*
***/
-void silc_pkcs_free(SilcPKCS pkcs);
+SilcBool silc_pkcs_register_default(void);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_is_supported
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_unregister_all
*
* SYNOPSIS
*
- * SilcBool silc_pkcs_is_supported(const unsigned char *name);
+ * SilcBool silc_pkcs_unregister_all(void);
*
* DESCRIPTION
*
- * Returns TRUE if PKCS algorithm `name' is supported.
+ * Unregister all PKCS and PKCS algorithms. Returns FALSE on error.
*
***/
-SilcBool silc_pkcs_is_supported(const unsigned char *name);
+SilcBool silc_pkcs_unregister_all(void);
/****f* silccrypt/SilcPKCSAPI/silc_pkcs_get_supported
*
***/
char *silc_pkcs_get_supported(void);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_generate_key
- *
- * SYNOPSIS
- *
- * SilcBool silc_pkcs_generate_key(SilcPKCS pkcs, SilcUInt32 bits_key_len,
- * SilcRng rng);
- *
- * DESCRIPTION
- *
- * Generate new key pair into the `pkcs' context. Returns FALSE on error.
- * If the `rng' is NULL global SILC RNG will be used.
- *
- ***/
-SilcBool silc_pkcs_generate_key(SilcPKCS pkcs, SilcUInt32 bits_key_len,
- SilcRng rng);
-
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_get_key_len
- *
- * SYNOPSIS
- *
- * SilcUInt32 silc_pkcs_get_key_len(SilcPKCS self);
- *
- * DESCRIPTION
- *
- * Returns the length of the key in bits.
- *
- ***/
-SilcUInt32 silc_pkcs_get_key_len(SilcPKCS self);
-
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_get_name
- *
- * SYNOPSIS
- *
- * const char *silc_pkcs_get_name(SilcPKCS pkcs);
- *
- * DESCRIPTION
- *
- * Returns PKCS name.
- *
- ***/
-const char *silc_pkcs_get_name(SilcPKCS pkcs);
-
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_get_public_key
- *
- * SYNOPSIS
- *
- * unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, SilcUInt32 *len);
- *
- * DESCRIPTION
- *
- * Returns SILC style public key for the PKCS. Note that this is not
- * the SILC Public Key, but the raw public key data from the PKCS.
- * The caller must free the returned data.
- *
- ***/
-unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, SilcUInt32 *len);
-
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_get_private_key
- *
- * SYNOPSIS
- *
- * unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs,
- * SilcUInt32 *len);
- *
- * DESCRIPTION
- *
- * Returns SILC style private key. Note that this is not SilcPrivateKey
- * but the raw private key bits from the PKCS. The caller must free the
- * returned data and SHOULD zero the memory area before freeing.
- *
- ***/
-unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, SilcUInt32 *len);
-
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_set
- *
- * SYNOPSIS
- *
- * SilcUInt32 silc_pkcs_public_key_set(SilcPKCS pkcs,
- * SilcPublicKey public_key);
- *
- * DESCRIPTION
- *
- * Sets public key from SilcPublicKey. Returns the length of the key in
- * bits.
- *
- ***/
-SilcUInt32 silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key);
-
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_data_set
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_find_pkcs
*
* SYNOPSIS
*
- * SilcUInt32 silc_pkcs_public_key_data_set(SilcPKCS pkcs,
- * unsigned char *pk,
- * SilcUInt32 pk_len);
+ * const SilcPKCSObject *silc_pkcs_get_pkcs(SilcPKCSType type);
*
* DESCRIPTION
*
- * Sets public key from data. Returns the length of the key.
+ * Finds PKCS context by the PKCS type.
*
***/
-SilcUInt32 silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
- SilcUInt32 pk_len);
+const SilcPKCSObject *silc_pkcs_find_pkcs(SilcPKCSType type);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_private_key_set
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_find_algorithm
*
* SYNOPSIS
*
- * SilcUInt32 silc_pkcs_private_key_set(SilcPKCS pkcs,
- * SilcPrivateKey private_key);
+ * const SilcPKCSAlgorithm *silc_pkcs_find_algorithm(const char *algorithm,
+ * const char *scheme);
*
* DESCRIPTION
*
- * Sets private key from SilcPrivateKey. Returns the length of the key
- * in bits.
+ * Finds PKCS algorithm context by the algorithm name `algorithm' and
+ * the algorithm scheme `scheme'. The `scheme' may be NULL.
*
***/
-SilcUInt32 silc_pkcs_private_key_set(SilcPKCS pkcs,
- SilcPrivateKey private_key);
+const SilcPKCSAlgorithm *silc_pkcs_find_algorithm(const char *algorithm,
+ const char *scheme);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_private_key_data_set
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_get_pkcs
*
* SYNOPSIS
*
- * SilcUInt32 silc_pkcs_private_key_data_set(SilcPKCS pkcs,
- * unsigned char *prv,
- * SilcUInt32 prv_len);
+ * const SilcPKCSObject *silc_pkcs_get_pkcs(SilcPublicKey public_key);
*
* DESCRIPTION
*
- * Sets private key from data. Returns the length of the key.
+ * Returns the PKCS object from `public_key'.
*
***/
-SilcUInt32 silc_pkcs_private_key_data_set(SilcPKCS pkcs, unsigned char *prv,
- SilcUInt32 prv_len);
+const SilcPKCSObject *silc_pkcs_get_pkcs(SilcPublicKey public_key);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_encrypt
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_get_algorithm
*
* SYNOPSIS
*
- * SilcBool silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src,
- * SilcUInt32 src_len, unsigned char *dst,
- * SilcUInt32 *dst_len);
+ * const SilcPKCSObject *silc_pkcs_get_algorithm(SilcPublicKey public_key);
*
* DESCRIPTION
*
- * Encrypts. Returns FALSE on error.
+ * Returns the PKCS algorithm object from `public_key'.
*
***/
-SilcBool silc_pkcs_encrypt(SilcPKCS pkcs, unsigned char *src,
- SilcUInt32 src_len,
- unsigned char *dst, SilcUInt32 *dst_len);
+const SilcPKCSAlgorithm *silc_pkcs_get_algorithm(SilcPublicKey public_key);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_decrypt
- *
- * SYNOPSIS
- *
- * SilcBool silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src,
- * SilcUInt32 src_len, unsigned char *dst,
- * SilcUInt32 *dst_len);
- *
- * DESCRIPTION
- *
- * Decrypts. Returns FALSE on error.
- *
- ***/
-SilcBool silc_pkcs_decrypt(SilcPKCS pkcs, unsigned char *src,
- SilcUInt32 src_len,
- unsigned char *dst, SilcUInt32 *dst_len);
-
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_sign
- *
- * SYNOPSIS
- *
- * SilcBool silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src,
- * SilcUInt32 src_len, unsigned char *dst,
- * SilcUInt32 *dst_len);
- *
- * DESCRIPTION
- *
- * Generates signature. Returns FALSE on error.
- *
- ***/
-SilcBool silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
- unsigned char *dst, SilcUInt32 *dst_len);
-
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_verify
- *
- * SYNOPSIS
- *
- * SilcBool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
- * SilcUInt32 signature_len, unsigned char *data,
- * SilcUInt32 data_len);
- *
- * DESCRIPTION
- *
- * Verifies signature. Returns FALSE on error. The 'signature' is
- * verified against the 'data'.
- *
- ***/
-SilcBool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
- SilcUInt32 signature_len, unsigned char *data,
- SilcUInt32 data_len);
-
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_sign_with_hash
- *
- * SYNOPSIS
- *
- * SilcBool silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
- * unsigned char *src, SilcUInt32 src_len,
- * unsigned char *dst, SilcUInt32 *dst_len);
- *
- * DESCRIPTION
- *
- * Generates signature with hash. The hash is signed. Returns FALSE on
- * error.
- *
- ***/
-SilcBool silc_pkcs_sign_with_hash(SilcPKCS pkcs, SilcHash hash,
- unsigned char *src, SilcUInt32 src_len,
- unsigned char *dst, SilcUInt32 *dst_len);
-
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_verify_with_hash
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_get_name
*
* SYNOPSIS
*
- * SilcBool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
- * unsigned char *signature,
- * SilcUInt32 signature_len,
- * unsigned char *data,
- * SilcUInt32 data_len);
+ * const char *silc_pkcs_get_name(SilcPublicKey public_key)
*
* DESCRIPTION
*
- * Verifies signature with hash. The `data' is hashed and verified against
- * the `signature'. Returns FALSE on error.
+ * Returns PKCS algorithm name from the public key.
*
***/
-SilcBool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
- unsigned char *signature,
- SilcUInt32 signature_len,
- unsigned char *data,
- SilcUInt32 data_len);
+const char *silc_pkcs_get_name(SilcPublicKey public_key);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_encode_identifier
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_get_type
*
* SYNOPSIS
*
- * char *silc_pkcs_encode_identifier(char *username, char *host,
- * char *realname, char *email,
- * char *org, char *country);
+ * SilcPKCSType silc_pkcs_get_type(SilcPublicKey public_key);
*
* DESCRIPTION
*
- * Encodes and returns SILC public key identifier. If some of the
- * arguments is NULL those are not encoded into the identifier string.
- * Protocol says that at least username and host must be provided.
+ * Returns PKCS type from the public key.
*
***/
-char *silc_pkcs_encode_identifier(char *username, char *host, char *realname,
- char *email, char *org, char *country);
+SilcPKCSType silc_pkcs_get_type(SilcPublicKey public_key);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_decode_identifier
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_get_context
*
* SYNOPSIS
*
- * SilcPublicKeyIdentifier silc_pkcs_decode_identifier(char *identifier);
+ * void *silc_pkcs_get_context(SilcPKCSType type, SilcPublicKey public_key);
*
* DESCRIPTION
*
- * Decodes the provided `identifier' and returns allocated context for
- * the identifier.
+ * Returns the internal PKCS `type' specific public key context from the
+ * `public_key'. The caller needs to explicitly type cast it to correct
+ * type. Returns NULL on error.
*
- ***/
-SilcPublicKeyIdentifier silc_pkcs_decode_identifier(char *identifier);
-
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_free_identifier
- *
- * SYNOPSIS
- *
- * void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier);
- *
- * DESCRIPTION
- *
- * Frees decoded public key identifier context. Call this to free the
- * context returned by the silc_pkcs_decode_identifier.
+ * For SILC_PKCS_SILC the returned context is SilcSILCPublicKey.
*
***/
-void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier);
+void *silc_pkcs_get_context(SilcPKCSType type, SilcPublicKey public_key);
/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_alloc
*
* SYNOPSIS
*
- * SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
- * const char *identifier,
- * const unsigned char *pk,
- * SilcUInt32 pk_len);
+ * SilcBool silc_pkcs_public_key_alloc(SilcPKCSType type,
+ * unsigned char *key,
+ * SilcUInt32 key_len
+ * SilcPublicKey *ret_public_key);
*
* DESCRIPTION
*
- * Allocates SILC style public key formed from sent arguments. The
- * 'name' is the algorithm (PKCS) name, the 'identifier' is the public
- * key identifier generated with silc_pkcs_encode_identifier, and the
- * 'pk' and 'pk_len' are the raw public key data returned for example
- * by silc_pkcs_get_public_key.
+ * Allocates SilcPublicKey of the type of `type' from the key data
+ * `key' of length of `key_len' bytes. Returns FALSE if the `key'
+ * is malformed or unsupported public key type. This function can be
+ * used to create public key from any kind of PKCS public keys that
+ * the implementation supports.
*
***/
-SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
- const char *identifier,
- const unsigned char *pk,
- SilcUInt32 pk_len);
+SilcBool silc_pkcs_public_key_alloc(SilcPKCSType type,
+ unsigned char *key,
+ SilcUInt32 key_len,
+ SilcPublicKey *ret_public_key);
/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_free
*
*
* DESCRIPTION
*
- * Frees public key and all data in it.
+ * Frees the public key.
*
***/
void silc_pkcs_public_key_free(SilcPublicKey public_key);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_private_key_alloc
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_export
*
* SYNOPSIS
*
- * SilcPrivateKey silc_pkcs_private_key_alloc(const char *name,
- * const unsigned char *prv,
- * SilcUInt32 prv_len);
+ * unsigned char *silc_pkcs_public_key_encode(SilcPublicKey public_key,
+ * SilcUInt32 *ret_len);
*
* DESCRIPTION
*
- * Allocates SILC private key formed from sent arguments. The 'name'
- * is the algorithm name, and the 'prv' and 'prv_len' are the raw
- * private key bits returned by silc_pkcs_get_private_key.
+ * Encodes the `public_key' into a binary format and returns it. Returns
+ * NULL on error. Caller must free the returned buffer.
*
***/
-SilcPrivateKey silc_pkcs_private_key_alloc(const char *name,
- const unsigned char *prv,
- SilcUInt32 prv_len);
+unsigned char *silc_pkcs_public_key_encode(SilcPublicKey public_key,
+ SilcUInt32 *ret_len);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_private_key_free
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_get_len
*
* SYNOPSIS
*
- * void silc_pkcs_private_key_free(SilcPrivateKey private_key);
+ * SilcUInt32 silc_pkcs_public_key_get_len(SilcPublicKey public_key);
*
* DESCRIPTION
*
- * Frees private key and all data in it. The private key is zeroed
- * before it is freed.
+ * Returns the key length in bits from the public key.
*
***/
-void silc_pkcs_private_key_free(SilcPrivateKey private_key);
+SilcUInt32 silc_pkcs_public_key_get_len(SilcPublicKey public_key);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_encode
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_compare
*
* SYNOPSIS
*
- * unsigned char *
- * silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len);
+ * SilcBool silc_pkcs_public_key_compare(SilcPublicKey key1,
+ * SilcPublicKey key2);
*
* DESCRIPTION
*
- * Encodes SILC style public key from SilcPublicKey. Returns the encoded
- * data.
+ * Compares two public keys and returns TRUE if they are same key, and
+ * FALSE if they are not same.
*
***/
-unsigned char *
-silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len);
+SilcBool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_data_encode
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_copy
*
* SYNOPSIS
*
- * unsigned char *
- * silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
- * char *pkcs, char *identifier,
- * SilcUInt32 *len);
+ * SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key);
*
* DESCRIPTION
*
- * Encodes SILC style public key. Returns the encoded data.
+ * Copies the public key indicated by `public_key' and returns new
+ * allocated public key which is indentical to the `public_key'.
*
***/
-unsigned char *
-silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
- char *pkcs, char *identifier,
- SilcUInt32 *len);
+SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_decode
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_private_key_alloc
*
* SYNOPSIS
*
- * SilcBool silc_pkcs_public_key_decode(unsigned char *data,
- * SilcUInt32 data_len,
- * SilcPublicKey *public_key);
+ * SilcBool silc_pkcs_private_key_alloc(SilcPKCSType type,
+ * unsigned char *key,
+ * SilcUInt32 key_len,
+ * SilcPrivateKey *ret_private_key);
*
* DESCRIPTION
*
- * Decodes SILC style public key. Returns TRUE if the decoding was
- * successful. Allocates new public key as well.
+ * Allocates SilcPrivateKey of the type of `type' from the key data
+ * `key' of length of `key_len' bytes. Returns FALSE if the `key'
+ * is malformed or unsupported private key type.
*
***/
-SilcBool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
- SilcPublicKey *public_key);
+SilcBool silc_pkcs_private_key_alloc(SilcPKCSType type,
+ unsigned char *key,
+ SilcUInt32 key_len,
+ SilcPrivateKey *ret_private_key);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_payload_encode
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_private_key_get_len
*
* SYNOPSIS
*
- * SilcBool silc_pkcs_public_key_payload_encode(SilcPublicKey public_key);
+ * SilcUInt32 silc_pkcs_private_key_get_len(SilcPrivateKey private_key);
*
* DESCRIPTION
*
- * Encodes the Public Key Payload from the public key indicated by
- * `public_key' of type of `pk_type'. The type is SilcSKEPKType.
- * Returns the encoded payload buffer.
+ * Returns the key length in bits from the public key.
*
***/
-SilcBuffer silc_pkcs_public_key_payload_encode(SilcPublicKey public_key);
+SilcUInt32 silc_pkcs_private_key_get_len(SilcPrivateKey private_key);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_payload_decode
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_private_key_free
*
* SYNOPSIS
*
- * SilcBool silc_pkcs_public_key_payload_decode(unsigned char *data,
- * SilcUInt32 data_len,
- * SilcPublicKey *public_key);
+ * void silc_pkcs_private_key_free(SilcPrivateKey private_key;
*
* DESCRIPTION
*
- * Decodes Public Key Payload from `data' of `data_len' bytes in length
- * data buffer into `public_key' pointer. Returns FALSE if the payload
- * cannot be decoded.
+ * Frees the private key.
*
***/
-SilcBool silc_pkcs_public_key_payload_decode(unsigned char *data,
- SilcUInt32 data_len,
- SilcPublicKey *public_key);
+void silc_pkcs_private_key_free(SilcPrivateKey private_key);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_compare
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_encrypt
*
* SYNOPSIS
*
- * SilcBool silc_pkcs_public_key_compare(SilcPublicKey key1,
- * SilcPublicKey key2);
+ * SilcBool silc_pkcs_encrypt(SilcPublicKey public_key,
+ * unsigned char *src, SilcUInt32 src_len,
+ * unsigned char *dst, SilcUInt32 dst_size,
+ * SilcUInt32 *dst_len);
*
* DESCRIPTION
*
- * Compares two public keys and returns TRUE if they are same key, and
- * FALSE if they are not same.
+ * Encrypts with the public key. Returns FALSE on error.
*
***/
-SilcBool silc_pkcs_public_key_compare(SilcPublicKey key1, SilcPublicKey key2);
+SilcBool silc_pkcs_encrypt(SilcPublicKey public_key,
+ unsigned char *src, SilcUInt32 src_len,
+ unsigned char *dst, SilcUInt32 dst_size,
+ SilcUInt32 *dst_len);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_public_key_copy
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_decrypt
*
* SYNOPSIS
*
- * SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key);
+ * SilcBool silc_pkcs_decrypt(SilcPrivateKey private_key,
+ * unsigned char *src, SilcUInt32 src_len,
+ * unsigned char *dst, SilcUInt32 dst_size,
+ * SilcUInt32 *dst_len);
*
* DESCRIPTION
*
- * Copies the public key indicated by `public_key' and returns new allocated
- * public key which is indentical to the `public_key'.
+ * Decrypts with the private key. Returns FALSE on error.
*
***/
-SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key);
+SilcBool silc_pkcs_decrypt(SilcPrivateKey private_key,
+ unsigned char *src, SilcUInt32 src_len,
+ unsigned char *dst, SilcUInt32 dst_size,
+ SilcUInt32 *dst_len);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_private_key_encode
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_sign
*
* SYNOPSIS
*
- * unsigned char *
- * silc_pkcs_private_key_encode(SilcPrivateKey private_key,
- * SilcUInt32 *len);
+ * SilcBool silc_pkcs_sign(SilcPrivateKey private_key,
+ * unsigned char *src, SilcUInt32 src_len,
+ * unsigned char *dst, SilcUInt32 dst_size,
+ * SilcUInt32 *dst_len, SilcHash hash);
*
* DESCRIPTION
*
- * Encodes SILC private key from SilcPrivateKey. Returns the encoded data.
+ * Generates signature with the private key. Returns FALSE on error.
+ * If `hash' is non-NULL the `src' will be hashed before signing.
*
***/
-unsigned char *
-silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len);
+SilcBool silc_pkcs_sign(SilcPrivateKey private_key,
+ unsigned char *src, SilcUInt32 src_len,
+ unsigned char *dst, SilcUInt32 dst_size,
+ SilcUInt32 *dst_len, SilcHash hash);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_private_key_data_encode
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_verify
*
* SYNOPSIS
*
- * unsigned char *
- * silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
- * char *pkcs, SilcUInt32 *len);
+ * SilcBool silc_pkcs_verify(SilcPublicKey public_key,
+ * unsigned char *signature,
+ * SilcUInt32 signature_len,
+ * unsigned char *data,
+ * SilcUInt32 data_len, SilcHash hash);
*
* DESCRIPTION
*
- * Encodes SILC private key. Returns the encoded data.
+ * Verifies signature. Returns FALSE on error. The 'signature' is
+ * verified against the 'data'. If the `hash' is non-NULL then the `data'
+ * will hashed before verification. If the `hash' is NULL, then the
+ * hash algorithm to be used is retrieved from the signature. If it
+ * isn't present in the signature the verification is done as is without
+ * hashing.
*
***/
-unsigned char *
-silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
- char *pkcs, SilcUInt32 *len);
+SilcBool silc_pkcs_verify(SilcPublicKey public_key,
+ unsigned char *signature,
+ SilcUInt32 signature_len,
+ unsigned char *data,
+ SilcUInt32 data_len, SilcHash hash);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_private_key_decode
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_load_public_key
*
* SYNOPSIS
*
- * SilcBool silc_pkcs_private_key_decode(unsigned char *data,
- * SilcUInt32 data_len,
- * SilcPrivateKey *private_key);
+ * SilcBool silc_pkcs_load_public_key(const char *filename,
+ * SilcPublicKey *ret_public_key);
*
* DESCRIPTION
*
- * Decodes SILC style private key. Returns TRUE if the decoding was
- * successful. Allocates new private key as well.
+ * Loads public key from file and allocates new public key. Returns TRUE
+ * if loading was successful.
*
***/
-SilcBool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
- SilcPrivateKey *private_key);
+SilcBool silc_pkcs_load_public_key(const char *filename,
+ SilcPublicKey *ret_public_key);
/****f* silccrypt/SilcPKCSAPI/silc_pkcs_save_public_key
*
* SYNOPSIS
*
* SilcBool silc_pkcs_save_public_key(const char *filename,
- * SilcPublicKey public_key,
- * SilcUInt32 encoding);
+ * SilcPublicKey public_key,
+ * SilcPKCSFileEncoding encoding);
*
* DESCRIPTION
*
- * Saves public key into file. Returns FALSE on error.
+ * Saves public key into file with specified encoding. Returns FALSE
+ * on error.
*
***/
-SilcBool silc_pkcs_save_public_key(const char *filename, SilcPublicKey public_key,
- SilcUInt32 encoding);
+SilcBool silc_pkcs_save_public_key(const char *filename,
+ SilcPublicKey public_key,
+ SilcPKCSFileEncoding encoding);
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_save_public_key_data
+/****f* silccrypt/SilcPKCSAPI/silc_pkcs_load_private_key
*
* SYNOPSIS
*
- * SilcBool silc_pkcs_save_public_key_data(const char *filename,
- * unsigned char *data,
- * SilcUInt32 data_len,
- * SilcUInt32 encoding);
+ * SilcBool silc_pkcs_load_private_key(const char *filename,
+ * const unsigned char *passphrase,
+ * SilcUInt32 passphrase_len,
+ * SilcPrivateKey *ret_private_key);
*
* DESCRIPTION
*
- * Saves public key into file. The public key is already encoded as
- * data when calling this function. Returns FALSE on error.
+ * Loads private key from file and allocates new private key. Returns TRUE
+ * if loading was successful. The `passphrase' is used as decryption
+ * key of the private key file, in case it is encrypted.
*
***/
-SilcBool silc_pkcs_save_public_key_data(const char *filename, unsigned char *data,
- SilcUInt32 data_len, SilcUInt32 encoding);
+SilcBool silc_pkcs_load_private_key(const char *filename,
+ const unsigned char *passphrase,
+ SilcUInt32 passphrase_len,
+ SilcPrivateKey *ret_private_key);
/****f* silccrypt/SilcPKCSAPI/silc_pkcs_save_private_key
*
* SYNOPSIS
*
* SilcBool silc_pkcs_save_private_key(const char *filename,
- * SilcPrivateKey private_key,
- * unsigned char *passphrase,
- * SilcUInt32 passphrase_len,
- * SilcUInt32 encoding);
+ * SilcPrivateKey private_key,
+ * const unsigned char *passphrase,
+ * SilcUInt32 passphrase_len,
+ * SilcPKCSFileEncoding encoding,
+ * SilcRng rng);
*
* DESCRIPTION
*
* Saves private key into file. The private key is encrypted into
- * the file with the `passphrase' as a key. The encryption algorithm
- * is AES with 256 bit key in CBC mode. Returns FALSE on error.
+ * the file with the `passphrase' as a key, if PKCS supports encrypted
+ * private keys. Returns FALSE on error.
*
***/
SilcBool silc_pkcs_save_private_key(const char *filename,
- SilcPrivateKey private_key,
- unsigned char *passphrase,
- SilcUInt32 passphrase_len,
- SilcUInt32 encoding);
-
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_load_public_key
- *
- * SYNOPSIS
- *
- * SilcBool silc_pkcs_load_public_key(const char *filename,
- * SilcPublicKey *public_key,
- * SilcUInt32 encoding);
- *
- * DESCRIPTION
- *
- * Loads public key from file and allocates new public key. Returns TRUE
- * if loading was successful.
- *
- ***/
-SilcBool silc_pkcs_load_public_key(const char *filename, SilcPublicKey *public_key,
- SilcUInt32 encoding);
-
-/****f* silccrypt/SilcPKCSAPI/silc_pkcs_load_private_key
- *
- * SYNOPSIS
- *
- * SilcBool silc_pkcs_load_private_key(const char *filename,
- * SilcPrivateKey *private_key,
- * unsigned char *passphrase,
- * SilcUInt32 passphrase_len,
- * SilcUInt32 encoding);
- *
- * DESCRIPTION
- *
- * Loads private key from file and allocates new private key. Returns TRUE
- * if loading was successful. The `passphrase' is used as decryption
- * key of the private key file.
- *
- ***/
-SilcBool silc_pkcs_load_private_key(const char *filename,
- SilcPrivateKey *private_key,
- unsigned char *passphrase,
- SilcUInt32 passphrase_len,
- SilcUInt32 encoding);
+ SilcPrivateKey private_key,
+ const unsigned char *passphrase,
+ SilcUInt32 passphrase_len,
+ SilcPKCSFileEncoding encoding,
+ SilcRng rng);
#endif /* !SILCPKCS_H */
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2003 Pekka Riikonen
+ Copyright (C) 2003 - 2006 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* $Id$ */
#include "silc.h"
-#include "silcpkcs1.h"
+#include "rsa.h"
+
+/************************** PKCS #1 message format ***************************/
/* Minimum padding in block */
#define SILC_PKCS1_MIN_PADDING 8
success. */
SilcBool silc_pkcs1_encode(SilcPkcs1BlockType bt,
- const unsigned char *data,
- SilcUInt32 data_len,
- unsigned char *dest_data,
- SilcUInt32 dest_data_size,
- SilcRng rng)
+ const unsigned char *data,
+ SilcUInt32 data_len,
+ unsigned char *dest_data,
+ SilcUInt32 dest_data_size,
+ SilcRng rng)
{
SilcInt32 padlen;
int i;
SILC_LOG_DEBUG(("PKCS#1 encoding, bt %d", bt));
if (!data || !dest_data ||
- dest_data_size < 3 || dest_data_size < data_len) {
+ dest_data_size < SILC_PKCS1_MIN_PADDING + 3 ||
+ dest_data_size < data_len) {
SILC_LOG_DEBUG(("Data to be encoded is too long"));
return FALSE;
}
Returns TRUE on success. */
SilcBool silc_pkcs1_decode(SilcPkcs1BlockType bt,
- const unsigned char *data,
- SilcUInt32 data_len,
- unsigned char *dest_data,
- SilcUInt32 dest_data_size,
- SilcUInt32 *dest_len)
+ const unsigned char *data,
+ SilcUInt32 data_len,
+ unsigned char *dest_data,
+ SilcUInt32 dest_data_size,
+ SilcUInt32 *dest_len)
{
int i = 0;
return TRUE;
}
+
+
+/***************************** PKCS #1 PKCS API ******************************/
+
+/* Generates RSA key pair. */
+
+SilcBool silc_pkcs1_generate_key(SilcUInt32 keylen,
+ SilcRng rng,
+ void **ret_public_key,
+ void **ret_private_key)
+{
+ SilcUInt32 prime_bits = keylen / 2;
+ SilcMPInt p, q;
+ SilcBool found = FALSE;
+
+ if (keylen < 768 || keylen > 16384)
+ return FALSE;
+
+ silc_mp_init(&p);
+ silc_mp_init(&q);
+
+ /* Find p and q */
+ while (!found) {
+ silc_math_gen_prime(&p, prime_bits, FALSE, rng);
+ silc_math_gen_prime(&q, prime_bits, FALSE, rng);
+ if ((silc_mp_cmp(&p, &q)) != 0)
+ found = TRUE;
+ }
+
+ /* If p is smaller than q, switch them */
+ if ((silc_mp_cmp(&p, &q)) > 0) {
+ SilcMPInt hlp;
+ silc_mp_init(&hlp);
+
+ silc_mp_set(&hlp, &p);
+ silc_mp_set(&p, &q);
+ silc_mp_set(&q, &hlp);
+
+ silc_mp_uninit(&hlp);
+ }
+
+ /* Generate the actual keys */
+ if (!rsa_generate_keys(keylen, &p, &q, ret_public_key, ret_private_key))
+ return FALSE;
+
+ silc_mp_uninit(&p);
+ silc_mp_uninit(&q);
+
+ return TRUE;
+}
+
+/* Import PKCS #1 compliant public key */
+
+SilcBool silc_pkcs1_import_public_key(unsigned char *key,
+ SilcUInt32 key_len,
+ void **ret_public_key)
+{
+ SilcAsn1 asn1 = NULL;
+ SilcBufferStruct alg_key;
+ RsaPublicKey *pubkey;
+
+ if (!ret_public_key)
+ return FALSE;
+
+ asn1 = silc_asn1_alloc();
+ if (!asn1)
+ return FALSE;
+
+ /* Allocate RSA public key */
+ *ret_public_key = pubkey = silc_calloc(1, sizeof(*pubkey));
+ if (!pubkey)
+ goto err;
+
+ /* Parse the PKCS #1 public key */
+ silc_buffer_set(&alg_key, key, key_len);
+ if (!silc_asn1_decode(asn1, &alg_key,
+ SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
+ SILC_ASN1_SEQUENCE,
+ SILC_ASN1_INT(&pubkey->n),
+ SILC_ASN1_INT(&pubkey->e),
+ SILC_ASN1_END, SILC_ASN1_END))
+ goto err;
+
+ /* Set key length */
+ pubkey->bits = silc_mp_sizeinbase(&pubkey->n, 2);
+
+ silc_asn1_free(asn1);
+
+ return TRUE;
+
+ err:
+ silc_asn1_free(asn1);
+ return FALSE;
+}
+
+/* Export PKCS #1 compliant public key */
+
+unsigned char *silc_pkcs1_export_public_key(void *public_key,
+ SilcUInt32 *ret_len)
+{
+ RsaPublicKey *key = public_key;
+ SilcAsn1 asn1 = NULL;
+ SilcBufferStruct alg_key;
+ unsigned char *ret;
+
+ asn1 = silc_asn1_alloc();
+ if (!asn1)
+ goto err;
+
+ /* Encode to PKCS #1 public key */
+ memset(&alg_key, 0, sizeof(alg_key));
+ if (!silc_asn1_encode(asn1, &alg_key,
+ SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
+ SILC_ASN1_SEQUENCE,
+ SILC_ASN1_INT(&key->n),
+ SILC_ASN1_INT(&key->e),
+ SILC_ASN1_END, SILC_ASN1_END))
+ goto err;
+
+ ret = silc_buffer_steal(&alg_key, ret_len);
+ silc_asn1_free(asn1);
+
+ return ret;
+
+ err:
+ if (asn1)
+ silc_asn1_free(asn1);
+ return NULL;
+}
+
+/* Returns key length */
+
+SilcUInt32 silc_pkcs1_public_key_bitlen(void *public_key)
+{
+ RsaPublicKey *key = public_key;
+ return key->bits;
+}
+
+/* Copy public key */
+
+void *silc_pkcs1_public_key_copy(void *public_key)
+{
+ RsaPublicKey *key = public_key, *new_key;
+
+ new_key = silc_calloc(1, sizeof(*new_key));
+ if (!new_key)
+ return NULL;
+
+ silc_mp_init(&new_key->n);
+ silc_mp_init(&new_key->e);
+ silc_mp_set(&new_key->n, &key->n);
+ silc_mp_set(&new_key->e, &key->e);
+ new_key->bits = key->bits;
+
+ return new_key;
+}
+
+/* Compare public keys */
+
+SilcBool silc_pkcs1_public_key_compare(void *key1, void *key2)
+{
+ RsaPublicKey *k1 = key1, *k2 = key2;
+
+ if (k1->bits != k2->bits)
+ return FALSE;
+ if (silc_mp_cmp(&k1->e, &k2->e) != 0)
+ return FALSE;
+ if (silc_mp_cmp(&k1->n, &k2->n) != 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Frees public key */
+
+void silc_pkcs1_public_key_free(void *public_key)
+{
+ RsaPublicKey *key = public_key;
+
+ silc_mp_uninit(&key->n);
+ silc_mp_uninit(&key->e);
+ silc_free(key);
+}
+
+/* Import PKCS #1 compliant private key */
+
+SilcBool silc_pkcs1_import_private_key(unsigned char *key,
+ SilcUInt32 key_len,
+ void **ret_private_key)
+{
+ SilcAsn1 asn1;
+ SilcBufferStruct alg_key;
+ RsaPrivateKey *privkey;
+
+ if (!ret_private_key)
+ return FALSE;
+
+ asn1 = silc_asn1_alloc();
+ if (!asn1)
+ return FALSE;
+
+ /* Allocate RSA private key */
+ *ret_private_key = privkey = silc_calloc(1, sizeof(*privkey));
+ if (!privkey)
+ goto err;
+
+ /* Parse the PKCS #1 private key */
+ silc_buffer_set(&alg_key, key, key_len);
+ if (!silc_asn1_decode(asn1, &alg_key,
+ SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
+ SILC_ASN1_SEQUENCE,
+ SILC_ASN1_INT(NULL),
+ SILC_ASN1_INT(&privkey->n),
+ SILC_ASN1_INT(&privkey->e),
+ SILC_ASN1_INT(&privkey->d),
+ SILC_ASN1_INT(&privkey->p),
+ SILC_ASN1_INT(&privkey->q),
+ SILC_ASN1_INT(&privkey->dP),
+ SILC_ASN1_INT(&privkey->dQ),
+ SILC_ASN1_INT(&privkey->qP),
+ SILC_ASN1_END, SILC_ASN1_END))
+ goto err;
+
+ /* Set key length */
+ privkey->bits = silc_mp_sizeinbase(&privkey->n, 2);
+
+ silc_asn1_free(asn1);
+
+ return TRUE;
+
+ err:
+ silc_asn1_free(asn1);
+ return FALSE;
+}
+
+/* Export PKCS #1 compliant private key */
+
+unsigned char *silc_pkcs1_export_private_key(void *private_key,
+ SilcUInt32 *ret_len)
+{
+ RsaPrivateKey *key = private_key;
+ SilcAsn1 asn1;
+ SilcBufferStruct alg_key;
+ SilcMPInt version;
+ unsigned char *ret;
+
+ asn1 = silc_asn1_alloc();
+ if (!asn1)
+ return FALSE;
+
+ /* Encode to PKCS #1 private key */
+ silc_mp_init(&version);
+ silc_mp_set_ui(&version, 0);
+ memset(&alg_key, 0, sizeof(alg_key));
+ if (!silc_asn1_encode(asn1, &alg_key,
+ SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
+ SILC_ASN1_SEQUENCE,
+ SILC_ASN1_INT(&version),
+ SILC_ASN1_INT(&key->n),
+ SILC_ASN1_INT(&key->e),
+ SILC_ASN1_INT(&key->d),
+ SILC_ASN1_INT(&key->p),
+ SILC_ASN1_INT(&key->q),
+ SILC_ASN1_INT(&key->dP),
+ SILC_ASN1_INT(&key->dQ),
+ SILC_ASN1_INT(&key->qP),
+ SILC_ASN1_END, SILC_ASN1_END))
+ goto err;
+ silc_mp_uninit(&version);
+
+ ret = silc_buffer_steal(&alg_key, ret_len);
+ silc_asn1_free(asn1);
+
+ return ret;
+
+ err:
+ silc_asn1_free(asn1);
+ return NULL;
+}
+
+/* Returns key length */
+
+SilcUInt32 silc_pkcs1_private_key_bitlen(void *private_key)
+{
+ RsaPrivateKey *key = private_key;
+ return key->bits;
+}
+
+/* Frees private key */
+
+void silc_pkcs1_private_key_free(void *private_key)
+{
+ RsaPrivateKey *key = private_key;
+
+ silc_mp_uninit(&key->n);
+ silc_mp_uninit(&key->e);
+ silc_mp_uninit(&key->d);
+ silc_mp_uninit(&key->dP);
+ silc_mp_uninit(&key->dQ);
+ silc_mp_uninit(&key->qP);
+ silc_mp_uninit(&key->p);
+ silc_mp_uninit(&key->q);
+ silc_free(key);
+}
+
+/* PKCS #1 RSA routines */
+
+SilcBool silc_pkcs1_encrypt(void *public_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *dst,
+ SilcUInt32 dst_size,
+ SilcUInt32 *ret_dst_len)
+{
+ RsaPublicKey *key = public_key;
+ SilcMPInt mp_tmp;
+ SilcMPInt mp_dst;
+ unsigned char padded[2048 + 1];
+ SilcUInt32 len = (key->bits + 7) / 8;
+
+ if (sizeof(padded) < len)
+ return FALSE;
+ if (dst_size < len)
+ return FALSE;
+
+ /* Pad data */
+ if (!silc_pkcs1_encode(SILC_PKCS1_BT_PUB, src, src_len,
+ padded, len, NULL))
+ return FALSE;
+
+ silc_mp_init(&mp_tmp);
+ silc_mp_init(&mp_dst);
+
+ /* Data to MP */
+ silc_mp_bin2mp(padded, len, &mp_tmp);
+
+ /* Encrypt */
+ rsa_public_operation(key, &mp_tmp, &mp_dst);
+
+ /* MP to data */
+ silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
+ *ret_dst_len = len;
+
+ memset(padded, 0, sizeof(padded));
+ silc_mp_uninit(&mp_tmp);
+ silc_mp_uninit(&mp_dst);
+
+ return TRUE;
+}
+
+SilcBool silc_pkcs1_decrypt(void *private_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *dst,
+ SilcUInt32 dst_size,
+ SilcUInt32 *ret_dst_len)
+{
+ RsaPrivateKey *key = private_key;
+ SilcMPInt mp_tmp;
+ SilcMPInt mp_dst;
+ unsigned char *padded, unpadded[2048 + 1];
+ SilcUInt32 padded_len;
+
+ if (dst_size < (key->bits + 7) / 8)
+ return FALSE;
+
+ silc_mp_init(&mp_tmp);
+ silc_mp_init(&mp_dst);
+
+ /* Data to MP */
+ silc_mp_bin2mp(src, src_len, &mp_tmp);
+
+ /* Decrypt */
+ rsa_private_operation(key, &mp_tmp, &mp_dst);
+
+ /* MP to data */
+ padded = silc_mp_mp2bin(&mp_dst, (key->bits + 7) / 8, &padded_len);
+
+ /* Unpad data */
+ if (!silc_pkcs1_decode(SILC_PKCS1_BT_PUB, padded, padded_len,
+ unpadded, sizeof(unpadded), ret_dst_len)) {
+ memset(padded, 0, padded_len);
+ silc_free(padded);
+ silc_mp_uninit(&mp_tmp);
+ silc_mp_uninit(&mp_dst);
+ return FALSE;
+ }
+
+ /* Copy to destination */
+ memcpy(dst, unpadded, *ret_dst_len);
+
+ memset(padded, 0, padded_len);
+ memset(unpadded, 0, sizeof(unpadded));
+ silc_free(padded);
+ silc_mp_uninit(&mp_tmp);
+ silc_mp_uninit(&mp_dst);
+
+ return TRUE;
+}
+
+SilcBool silc_pkcs1_sign(void *private_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *signature,
+ SilcUInt32 signature_size,
+ SilcUInt32 *ret_signature_len,
+ SilcHash hash)
+{
+ return FALSE;
+}
+
+SilcBool silc_pkcs1_verify(void *public_key,
+ unsigned char *signature,
+ SilcUInt32 signature_len,
+ unsigned char *data,
+ SilcUInt32 data_len,
+ SilcHash hash)
+{
+ return FALSE;
+}
+
+/* PKCS #1 sign without hash oid */
+
+SilcBool silc_pkcs1_sign_no_oid(void *private_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *signature,
+ SilcUInt32 signature_size,
+ SilcUInt32 *ret_signature_len,
+ SilcHash hash)
+{
+ RsaPrivateKey *key = private_key;
+ SilcMPInt mp_tmp;
+ SilcMPInt mp_dst;
+ unsigned char padded[2048 + 1], hashr[SILC_HASH_MAXLEN];
+ SilcUInt32 len = (key->bits + 7) / 8;
+
+ if (sizeof(padded) < len)
+ return FALSE;
+ if (signature_size < len)
+ return FALSE;
+
+ /* Compute hash if requested */
+ if (hash) {
+ silc_hash_make(hash, src, src_len, hashr);
+ src = hashr;
+ src_len = silc_hash_len(hash);
+ }
+
+ /* Pad data */
+ if (!silc_pkcs1_encode(SILC_PKCS1_BT_PRV1, src, src_len,
+ padded, len, NULL))
+ return FALSE;
+
+ silc_mp_init(&mp_tmp);
+ silc_mp_init(&mp_dst);
+
+ /* Data to MP */
+ silc_mp_bin2mp(padded, len, &mp_tmp);
+
+ /* Sign */
+ rsa_private_operation(key, &mp_tmp, &mp_dst);
+
+ /* MP to data */
+ silc_mp_mp2bin_noalloc(&mp_dst, signature, len);
+ *ret_signature_len = len;
+
+ memset(padded, 0, sizeof(padded));
+ silc_mp_uninit(&mp_tmp);
+ silc_mp_uninit(&mp_dst);
+ if (hash)
+ memset(hashr, 0, sizeof(hashr));
+
+ return TRUE;
+}
+
+/* PKCS #1 verify without hash oid */
+
+SilcBool silc_pkcs1_verify_no_oid(void *public_key,
+ unsigned char *signature,
+ SilcUInt32 signature_len,
+ unsigned char *data,
+ SilcUInt32 data_len,
+ SilcHash hash)
+{
+ RsaPublicKey *key = public_key;
+ int ret = TRUE;
+ SilcMPInt mp_tmp2;
+ SilcMPInt mp_dst;
+ unsigned char *verify, unpadded[2048 + 1], hashr[SILC_HASH_MAXLEN];
+ SilcUInt32 verify_len, len = (key->bits + 7) / 8;
+
+ silc_mp_init(&mp_tmp2);
+ silc_mp_init(&mp_dst);
+
+ /* Format the signature into MP int */
+ silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
+
+ /* Verify */
+ rsa_public_operation(key, &mp_tmp2, &mp_dst);
+
+ /* MP to data */
+ verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);
+
+ /* Unpad data */
+ if (!silc_pkcs1_decode(SILC_PKCS1_BT_PRV1, verify, verify_len,
+ unpadded, sizeof(unpadded), &len)) {
+ memset(verify, 0, verify_len);
+ silc_free(verify);
+ silc_mp_uninit(&mp_tmp2);
+ silc_mp_uninit(&mp_dst);
+ return FALSE;
+ }
+
+ /* Hash data if requested */
+ if (hash) {
+ silc_hash_make(hash, data, data_len, hashr);
+ data = hashr;
+ }
+
+ /* Compare */
+ if (memcmp(data, unpadded, len))
+ ret = FALSE;
+
+ memset(verify, 0, verify_len);
+ memset(unpadded, 0, sizeof(unpadded));
+ silc_free(verify);
+ silc_mp_uninit(&mp_tmp2);
+ silc_mp_uninit(&mp_dst);
+ if (hash)
+ memset(hashr, 0, sizeof(hashr));
+
+ return ret;
+}
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2003 Pekka Riikonen
+ Copyright (C) 2003 - 2005 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*
***/
SilcBool silc_pkcs1_encode(SilcPkcs1BlockType bt,
- const unsigned char *data,
- SilcUInt32 data_len,
- unsigned char *dest_data,
- SilcUInt32 dest_data_size,
- SilcRng rng);
+ const unsigned char *data,
+ SilcUInt32 data_len,
+ unsigned char *dest_data,
+ SilcUInt32 dest_data_size,
+ SilcRng rng);
/****f* silccrypt/SilcPKCS1API/silc_pkcs1_decode
*
*
***/
SilcBool silc_pkcs1_decode(SilcPkcs1BlockType bt,
- const unsigned char *data,
- SilcUInt32 data_len,
- unsigned char *dest_data,
- SilcUInt32 dest_data_size,
- SilcUInt32 *dest_len);
+ const unsigned char *data,
+ SilcUInt32 data_len,
+ unsigned char *dest_data,
+ SilcUInt32 dest_data_size,
+ SilcUInt32 *dest_len);
#endif /* SILCPKCS1_H */
--- /dev/null
+/*
+
+ silcpkcs1_i.h
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C); 2006 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#ifndef SILCPKCS1_I_H
+#define SILCPKCS1_I_H
+
+SilcBool silc_pkcs1_generate_key(SilcUInt32 keylen,
+ SilcRng rng,
+ void **ret_public_key,
+ void **ret_private_key);
+SilcBool silc_pkcs1_import_public_key(unsigned char *key,
+ SilcUInt32 key_len,
+ void **ret_public_key);
+unsigned char *silc_pkcs1_export_public_key(void *public_key,
+ SilcUInt32 *ret_len);
+SilcUInt32 silc_pkcs1_public_key_bitlen(void *public_key);
+void *silc_pkcs1_public_key_copy(void *public_key);
+SilcBool silc_pkcs1_public_key_compare(void *key1, void *key2);
+void silc_pkcs1_public_key_free(void *public_key);
+SilcBool silc_pkcs1_import_private_key(unsigned char *key,
+ SilcUInt32 key_len,
+ void **ret_private_key);
+unsigned char *silc_pkcs1_export_private_key(void *private_key,
+ SilcUInt32 *ret_len);
+SilcUInt32 silc_pkcs1_private_key_bitlen(void *private_key);
+void silc_pkcs1_private_key_free(void *private_key);
+SilcBool silc_pkcs1_encrypt(void *public_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *dst,
+ SilcUInt32 dst_size,
+ SilcUInt32 *ret_dst_len);
+SilcBool silc_pkcs1_decrypt(void *private_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *dst,
+ SilcUInt32 dst_size,
+ SilcUInt32 *ret_dst_len);
+SilcBool silc_pkcs1_sign(void *private_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *signature,
+ SilcUInt32 signature_size,
+ SilcUInt32 *ret_signature_len,
+ SilcHash hash);
+SilcBool silc_pkcs1_verify(void *public_key,
+ unsigned char *signature,
+ SilcUInt32 signature_len,
+ unsigned char *data,
+ SilcUInt32 data_len,
+ SilcHash hash);
+SilcBool silc_pkcs1_sign_no_oid(void *private_key,
+ unsigned char *src,
+ SilcUInt32 src_len,
+ unsigned char *signature,
+ SilcUInt32 signature_size,
+ SilcUInt32 *ret_signature_len,
+ SilcHash hash);
+SilcBool silc_pkcs1_verify_no_oid(void *public_key,
+ unsigned char *signature,
+ SilcUInt32 signature_len,
+ unsigned char *data,
+ SilcUInt32 data_len,
+ SilcHash hash);
+
+#endif /* SILCPKCS1_I_H */
size = (len ? len : ((silc_mp_sizeinbase(val, 2) + 7) / 8));
ret = silc_calloc(size, sizeof(*ret));
+ if (!ret)
+ return NULL;
silc_mp_init(&tmp);
silc_mp_set(&tmp, val);
/*
silcmath.h
-
+
Author: Pekka Riikonen <priikone@silcnet.org>
-
- Copyright (C) 1997 - 2001 Pekka Riikonen
-
+
+ Copyright (C) 1997 - 2005 Pekka Riikonen
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* SYNOPSIS
*
- * int silc_math_gen_prime(SilcMPInt *prime, SilcUInt32 bits, SilcBool verbose,
- * SilcRng);
+ * SilcBool silc_math_gen_prime(SilcMPInt *prime, SilcUInt32 bits,
+ * SilcBool verbose, SilcRng rng);
*
* DESCRIPTION
*
- * Find appropriate prime. It generates a number by taking random bytes.
- * It then tests the number that it's not divisible by any of the small
- * primes and then it performs Fermat's prime test. I thank Rieks Joosten
- * (r.joosten@pijnenburg.nl) for such a good help with prime tests.
+ * Find appropriate prime. It generates a number by taking random bytes.
+ * It then tests the number that it's not divisible by any of the small
+ * primes and then it performs Fermat's prime test. I thank Rieks Joosten
+ * (r.joosten@pijnenburg.nl) for such a good help with prime tests.
*
* If argument verbose is TRUE this will display some status information
* about the progress of generation. If the `rng' is NULL then global
*
* DESCRIPTION
*
- * Performs primality testings for given number. Returns TRUE if the
+ * Performs primality testings for given number. Returns TRUE if the
* number is probably a prime.
*
***/
* DESCRIPTION
*
* Same as silc_mp_mp2bin but does not allocate any memory. The
- * encoded data is returned into `dst' and it's length to the `ret_len'.
+ * encoded data is returned into `dst' of size of `dst_len'.
*
***/
void silc_mp_mp2bin_noalloc(SilcMPInt *val, unsigned char *dst,
server->params->server_info->public_key = NULL;
server->params->server_info->private_key = NULL;
- /* Allocate PKCS context for local public and private keys */
- if (!silc_pkcs_alloc(server->public_key->name, SILC_PKCS_SILC,
- &server->pkcs))
- goto err;
- silc_pkcs_public_key_set(server->pkcs, server->public_key);
- silc_pkcs_private_key_set(server->pkcs, server->private_key);
-
/* Create network listener(s) */
server->listeners = silc_dlist_init();
if (!server->listeners)
SilcUInt16 cmd_ident;
/* Server public key */
- SilcPKCS pkcs;
SilcPublicKey public_key;
SilcPrivateKey private_key;
static void
silc_server_accept_verify_key(SilcSKE ske,
- const unsigned char *pk_data,
- SilcUInt32 pk_len,
SilcSKEPKType pk_type,
+ SilcPublicKey public_key,
void *context,
SilcSKEVerifyCbCompletion completion,
void *completion_context)
silc_mutex_lock(thread->server->lock);
- /* Check for double free */
#if defined(SILC_DEBUG)
+ /* Check for double free */
assert(cmd->packet != NULL);
#endif /* SILC_DEBUG */
tmp = silc_argument_get_arg_type(args, 3, &len);
if (!tmp)
goto out;
- if (!silc_pkcs_public_key_payload_decode(tmp, len, &public_key))
+ if (!silc_public_key_payload_decode(tmp, len, &public_key))
goto out;
/* Store the public key */
return SILC_FSM_CONTINUE;
break;
- case SILC_PACKET_CONNECTION_AUTH_REQUEST:
- /** Packet CONNECTION_AUTH_REQUEST */
- if (packet->flags & SILC_PACKET_FLAG_LIST)
- break;
- silc_fsm_next(fsm, silc_server_st_packet_connection_auth_request);
- return SILC_FSM_CONTINUE;
- break;
-
case SILC_PACKET_HEARTBEAT:
case SILC_PACKET_SUCCESS:
case SILC_PACKET_FAILURE:
if (argc > 1 && !strcmp(argv[1], "-d")) {
silc_log_debug(TRUE);
silc_log_debug_hexdump(TRUE);
- silc_log_set_debug_string("*server*,*skr*,*ske*,*connauth*,*packet*,*stream*,*net*");
+ silc_log_set_debug_string("*server*,*skr*,*ske*,*connauth*,*packet*,*stream*,*net*,*pkcs*,*asn1*");
}
SILC_LOG_DEBUG(("Allocating scheduler"));
goto err;
info->server_name = strdup("test server");
- if (!silc_load_key_pair("test.pub", "test.prv", "", NULL,
+ if (!silc_load_key_pair("test.pub", "test.prv", "",
&info->public_key,
&info->private_key)) {
if (!silc_create_key_pair("rsa", 2048, "test.pub", "test.prv", NULL, "",
- NULL,
&info->public_key,
&info->private_key, FALSE)) {
goto err;
SILC_LOG_DEBUG(("Proposed PKCS alg `%s'", item));
- if (silc_pkcs_is_supported(item) == TRUE) {
+ if (silc_pkcs_find_algorithm(item, NULL)) {
SILC_LOG_DEBUG(("Found PKCS alg `%s'", item));
payload->pkcs_alg_len = len;
return SILC_SKE_STATUS_ERROR;
}
+ SILC_LOG_HEXDUMP(("hash buf"), buf->data, silc_buffer_len(buf));
+
memset(e, 0, e_len);
silc_free(e);
}
if (ske->prop) {
if (ske->prop->group)
silc_ske_group_free(ske->prop->group);
- if (ske->prop->pkcs)
- silc_pkcs_free(ske->prop->pkcs);
if (ske->prop->cipher)
silc_cipher_free(ske->prop->cipher);
if (ske->prop->hash)
prop->group = group;
- if (silc_pkcs_alloc(payload->pkcs_alg_list, ske->pk_type,
- &prop->pkcs) == FALSE) {
+ if (silc_pkcs_find_algorithm(payload->pkcs_alg_list, NULL) == NULL) {
status = SILC_SKE_STATUS_UNKNOWN_PKCS;
goto err;
}
silc_ske_group_free(group);
- if (prop->pkcs)
- silc_pkcs_free(prop->pkcs);
if (prop->cipher)
silc_cipher_free(prop->cipher);
if (prop->hash)
SILC_LOG_DEBUG(("Signing HASH_i value"));
/* Sign the hash value */
- silc_pkcs_private_key_data_set(ske->prop->pkcs, ske->private_key->prv,
- ske->private_key->prv_len);
- if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
- !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
+ if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
+ sizeof(sign) - 1, &sign_len, NULL)) {
/** Error computing signature */
silc_mp_uninit(x);
silc_free(x);
silc_mp_pow_mod(KEY, &payload->x, ske->x, &ske->prop->group->group);
ske->KEY = KEY;
- if (payload->pk_data && ske->callbacks->verify_key) {
+ /* Decode the remote's public key */
+ if (payload->pk_data &&
+ !silc_pkcs_public_key_alloc(payload->pk_type,
+ payload->pk_data, payload->pk_len,
+ &ske->prop->public_key)) {
+ SILC_LOG_ERROR(("Unsupported/malformed public key received"));
+ status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
+ goto err;
+ }
+
+ if (ske->prop->public_key && ske->callbacks->verify_key) {
SILC_LOG_DEBUG(("Verifying public key"));
/** Waiting public key verification */
silc_fsm_next(fsm, silc_ske_st_initiator_phase4);
- SILC_FSM_CALL(ske->callbacks->verify_key(ske, payload->pk_data,
- payload->pk_len,
+ SILC_FSM_CALL(ske->callbacks->verify_key(ske,
payload->pk_type,
+ ske->prop->public_key,
ske->callbacks->context,
silc_ske_pk_verified, NULL));
/* NOT REACHED */
SilcSKEKEPayload payload;
unsigned char hash[SILC_HASH_MAXLEN];
SilcUInt32 hash_len;
- SilcPublicKey public_key = NULL;
int key_len, block_len;
if (ske->aborted) {
payload = ske->ke2_payload;
- if (payload->pk_data) {
- /* Decode the public key */
- if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
- &public_key)) {
- SILC_LOG_ERROR(("Unsupported/malformed public key received"));
- status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
- goto err;
- }
-
+ if (ske->prop->public_key) {
SILC_LOG_DEBUG(("Public key is authentic"));
/* Compute the hash value */
SILC_LOG_DEBUG(("Verifying signature (HASH)"));
/* Verify signature */
- silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
- if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
- payload->sign_len, hash, hash_len) == FALSE) {
+ if (!silc_pkcs_verify(ske->prop->public_key, payload->sign_data,
+ payload->sign_len, hash, hash_len, NULL)) {
SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
goto err;
SILC_LOG_DEBUG(("Signature is Ok"));
- silc_pkcs_public_key_free(public_key);
memset(hash, 'F', hash_len);
}
silc_free(ske->KEY);
ske->KEY = NULL;
- if (public_key)
- silc_pkcs_public_key_free(public_key);
-
if (ske->hash) {
memset(ske->hash, 'F', hash_len);
silc_free(ske->hash);
/* XXX these shouldn't be allocated before we know the remote's
public key type. It's unnecessary to allocate these because the
select_security_properties has succeeded already. */
- if (silc_pkcs_alloc(ske->start_payload->pkcs_alg_list,
- SILC_PKCS_SILC, &prop->pkcs) == FALSE) {
+ if (!silc_pkcs_find_algorithm(ske->start_payload->pkcs_alg_list, NULL)) {
status = SILC_SKE_STATUS_UNKNOWN_PKCS;
goto err;
}
if (group)
silc_ske_group_free(group);
- if (prop->pkcs)
- silc_pkcs_free(prop->pkcs);
if (prop->cipher)
silc_cipher_free(prop->cipher);
if (prop->hash)
return SILC_FSM_CONTINUE;
}
- if (recv_payload->pk_data && ske->callbacks->verify_key) {
+ /* Decode the remote's public key */
+ if (recv_payload->pk_data &&
+ !silc_pkcs_public_key_alloc(recv_payload->pk_type,
+ recv_payload->pk_data,
+ recv_payload->pk_len,
+ &ske->prop->public_key)) {
+ /** Error decoding public key */
+ SILC_LOG_ERROR(("Unsupported/malformed public key received"));
+ ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
+ silc_fsm_next(fsm, silc_ske_st_responder_error);
+ return SILC_FSM_CONTINUE;
+ }
+
+ if (ske->prop->public_key && ske->callbacks->verify_key) {
SILC_LOG_DEBUG(("Verifying public key"));
/** Waiting public key verification */
silc_fsm_next(fsm, silc_ske_st_responder_phase4);
- SILC_FSM_CALL(ske->callbacks->verify_key(ske, recv_payload->pk_data,
- recv_payload->pk_len,
+ SILC_FSM_CALL(ske->callbacks->verify_key(ske,
recv_payload->pk_type,
+ ske->prop->public_key,
ske->callbacks->context,
silc_ske_pk_verified, NULL));
/* NOT REACHED */
Authentication flag is set. */
if (ske->start_payload &&
ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
- SilcPublicKey public_key = NULL;
unsigned char hash[SILC_HASH_MAXLEN];
SilcUInt32 hash_len;
- /* Decode the public key */
- if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
- recv_payload->pk_len,
- &public_key)) {
- /** Error decoding public key */
- SILC_LOG_ERROR(("Unsupported/malformed public key received"));
- ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
- silc_fsm_next(fsm, silc_ske_st_responder_error);
- return SILC_FSM_CONTINUE;
- }
-
SILC_LOG_DEBUG(("Public key is authentic"));
/* Compute the hash value */
SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
/* Verify signature */
- silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
- if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
- recv_payload->sign_len, hash, hash_len) == FALSE) {
+ if (!silc_pkcs_verify(ske->prop->public_key, recv_payload->sign_data,
+ recv_payload->sign_len, hash, hash_len, NULL)) {
/** Incorrect signature */
SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
SILC_LOG_DEBUG(("Signature is Ok"));
- silc_pkcs_public_key_free(public_key);
memset(hash, 'F', hash_len);
}
SILC_LOG_DEBUG(("Signing HASH value"));
/* Sign the hash value */
- silc_pkcs_private_key_data_set(ske->prop->pkcs, ske->private_key->prv,
- ske->private_key->prv_len);
- if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
- !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
+ if (!silc_pkcs_sign(ske->private_key, hash, hash_len, sign,
+ sizeof(sign) - 1, &sign_len, NULL)) {
/** Error computing signature */
status = SILC_SKE_STATUS_SIGNATURE_ERROR;
silc_fsm_next(fsm, silc_ske_st_responder_error);
SilcCipher cipher; /* Selected cipher */
SilcHmac hmac; /* Selected HMAC */
SilcHash hash; /* Selected hash algorithm */
- SilcPKCS pkcs; /* Selected PKCS and remote's
- public key/certificate */
+ SilcPublicKey public_key; /* Remote public key */
} *SilcSKESecurityProperties;
/***/
* SYNOPSIS
*
* typedef void (*SilcSKEVerifyCb)(SilcSKE ske,
- * const unsigned char *pk_data,
- * SilcUInt32 pk_len,
* SilcSKEPKType pk_type,
+ * SilcPublicKey public_key,
* void *context,
* SilcSKEVerifyCbCompletion completion,
* void *completion_context);
*
***/
typedef void (*SilcSKEVerifyCb)(SilcSKE ske,
- const unsigned char *pk_data,
- SilcUInt32 pk_len,
SilcSKEPKType pk_type,
+ SilcPublicKey public_key,
void *context,
SilcSKEVerifyCbCompletion completion,
void *completion_context);
break;
case SILC_SKR_FIND_PUBLIC_KEY:
- snprintf(retbuf, retbuf_size, "[%s] [%s]", find_name[type],
- ((SilcPublicKey)data)->identifier);
+ snprintf(retbuf, retbuf_size, "[%s] [%p]", find_name[type], data);
break;
default:
/* Destroy key */
entry->refcnt--;
- if (entry->refcnt == 0) {
- switch (entry->key.pk_type) {
- case SILC_PKCS_SILC:
- silc_pkcs_public_key_free(entry->key.key);
- break;
-
- default:
- break;
- }
+ if (entry->refcnt > 0)
+ return;
- silc_free(entry);
- }
+ silc_pkcs_public_key_free(entry->key.key);
+ silc_free(entry);
}
/* Hash table hash function for key entries */
SilcSKRKeyUsage usage,
void *key_context)
{
- SilcPublicKeyIdentifier ident = NULL;
SilcSKRKeyInternal key;
SilcSKRStatus status = SILC_SKR_ERROR;
+ SilcPublicKeyIdentifier ident;
+ SilcSILCPublicKey silc_pubkey;
+
+ /* Get the SILC public key */
+ silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
+ ident = &silc_pubkey->identifier;
- SILC_LOG_DEBUG(("Adding SILC public key [%s]", public_key->identifier));
+ SILC_LOG_DEBUG(("Adding SILC public key [%s]", ident->username));
silc_mutex_lock(skr->lock);
public_key, NULL, key_context, 0)) {
silc_mutex_unlock(skr->lock);
SILC_LOG_DEBUG(("Key already added"));
- return status;
+ return status | SILC_SKR_ALREADY_EXIST;
}
/* Allocate key entry */
}
key->key.usage = usage;
- key->key.pk_type = public_key->pk_type;
key->key.key = public_key;
key->key.key_context = key_context;
- ident = silc_pkcs_decode_identifier(public_key->identifier);
- if (!ident) {
- silc_mutex_unlock(skr->lock);
- silc_pkcs_free_identifier(ident);
- return status | SILC_SKR_NO_MEMORY;
- }
-
/* Add key specifics */
if (!silc_skr_add_entry(skr, SILC_SKR_FIND_PUBLIC_KEY,
key->refcnt++;
if (!silc_skr_add_entry(skr, SILC_SKR_FIND_PKCS_TYPE,
- SILC_32_TO_PTR(public_key->pk_type), key))
+ SILC_32_TO_PTR(SILC_PKCS_SILC), key))
goto err;
key->refcnt++;
silc_mutex_unlock(skr->lock);
- silc_free(ident);
return SILC_SKR_OK;
err:
silc_mutex_unlock(skr->lock);
- silc_free(ident);
return status;
}
SilcSKRKeyInternal key;
SilcSKRStatus status = SILC_SKR_ERROR;
- SILC_LOG_DEBUG(("Adding SILC public key [%s]", public_key->identifier));
+ SILC_LOG_DEBUG(("Adding SILC public key"));
silc_mutex_lock(skr->lock);
public_key, NULL, key_context, 0)) {
silc_mutex_unlock(skr->lock);
SILC_LOG_DEBUG(("Key already added"));
- return status;
+ return status | SILC_SKR_ALREADY_EXIST;
}
/* Allocate key entry */
}
key->key.usage = usage;
- key->key.pk_type = public_key->pk_type;
key->key.key = public_key;
key->key.key_context = key_context;
SilcSKRKeyUsage usage,
void *key_context)
{
+ SilcPKCSType type;
+
if (!public_key)
return SILC_SKR_ERROR;
+ type = silc_pkcs_get_type(public_key);
+
SILC_LOG_DEBUG(("Adding public key to repository"));
- switch (public_key->pk_type) {
+ switch (type) {
case SILC_PKCS_SILC:
return silc_skr_add_silc(skr, public_key, usage, key_context);
SilcSKRKeyUsage usage,
void *key_context)
{
+ SilcPKCSType type;
+
if (!public_key)
return SILC_SKR_ERROR;
+ type = silc_pkcs_get_type(public_key);
+
SILC_LOG_DEBUG(("Adding public key to repository"));
- switch (public_key->pk_type) {
+ switch (type) {
case SILC_PKCS_SILC:
return silc_skr_add_silc_simple(skr, public_key, usage, key_context);
return NULL;
}
-
-/* Helper function to find specificly SILC style public keys */
-
-SilcAsyncOperation silc_skr_find_silc(SilcSKR skr,
- SilcPublicKey public_key,
- SilcSKRFindCallback callback,
- void *callback_context)
-{
- SilcSKRFind find = NULL;
- SilcAsyncOperation op;
-
- SILC_LOG_DEBUG(("Finding SILC public key"));
-
- if (!public_key || public_key->pk_type != SILC_PKCS_SILC)
- goto err;
-
- find = silc_skr_find_alloc();
- if (!find)
- goto err;
-
- if (!silc_skr_find_set_public_key(find, public_key))
- goto err;
-
- op = silc_skr_find(skr, find, callback, callback_context);
-
- return op;
-
- err:
- if (find)
- silc_skr_find_free(find);
- callback(skr, NULL, SILC_SKR_ERROR, NULL, callback_context);
- return NULL;
-}
*
* NAME
*
- * typedef struct SilcSKRKeyStruct { ... } *SilcSKRKey
+ * typedef struct SilcSKRKeyStruct { ... } *SilcSKRKey;
*
* DESCRIPTION
*
- * This context holds the public key cryptosystem key type and the key
- * context that has been saved in the key repository. This context is
- * returned in the SilcSKRFindCallback list. Each entry in the list is
- * SilcSKRKey.
- *
- * The key context saved in SilcSKRKey is based on the PKCS type and
- * caller can explicitly type cast the key to correct type based on the
- * PKCS type.
+ * This context holds the public key, optional public key specific
+ * context and public key usage bits. This context is returned in
+ * the SilcSKRFindCallback list. Each entry in the list is SIlcSKRKey.
*
* SOURCE
*
*/
typedef struct SilcSKRKeyStruct {
SilcSKRKeyUsage usage; /* Key usage */
- SilcPKCSType pk_type; /* PKCS type */
- void *key; /* SILC_PKCS_SILC: SilcPublicKey */
+ SilcPublicKey key; /* Public key */
void *key_context; /* Optional key specific context */
} *SilcSKRKey;
/***/
*
* // Add a key to repository
* if (silc_skr_add_public_key(repository, public_key,
- * SILC_SKR_USAGW_ANY, NULL) != SILC_SKR_OK)
+ * SILC_SKR_USAGE_ANY, NULL) != SILC_SKR_OK)
* goto error;
*
***/
* `find'. As the finding procedure may be asynchronous this returns
* SilcAsyncOperation that may be used to control (like abort) the
* operation. The `callback' with `callback_context' will be called
- * to return found keys. If this returns NULL, operation cannot be
- * controlled, however it is not an error.
+ * to return found keys. If this returns NULL the finding was not
+ * asynchronous, and the `callback' has been called already.
*
***/
SilcAsyncOperation silc_skr_find(SilcSKR skr, SilcSKRFind find,
SilcSKRFindCallback callback,
void *callback_context);
-/****f* silcskr/SilcSKRAPI/silc_skr_find_silc
- *
- * SYNOPSIS
- *
- * SilcAsyncOperation silc_skr_find_silc(SilcSKR skr,
- * SilcPublicKey public_key,
- * SilcSKRFindCallback callback,
- * void *callback_context);
- *
- * DESCRIPTION
- *
- * A helper function that can be used to find specificly SILC style
- * public keys from the repository. This returns found key(s) by
- * the `public_key'. As the finding procedure may be asynchronous
- * this returns SilcAsyncOperation that may be used to control (like
- * abort) the operation. The `callback' with `callback_context' will
- * be called to return found keys. If this returns NULL, operation
- * cannot be controlled, however it is not an error.
- *
- ***/
-SilcAsyncOperation silc_skr_find_silc(SilcSKR skr,
- SilcPublicKey public_key,
- SilcSKRFindCallback callback,
- void *callback_context);
-
#include "silcskr_i.h"
#endif /* SILCSKR_H */
/* Create default email address, whether it is right or not */
snprintf(email, sizeof(email), "%s@%s", username, hostname);
- ident = silc_pkcs_encode_identifier(username, hostname, realname, email,
- NULL, NULL);
+ ident = silc_pkcs_silc_encode_identifier(username, hostname, realname,
+ email, NULL, NULL);
if (realname)
silc_free(realname);
silc_free(hostname);
/* Generate key pair */
SilcBool silc_create_key_pair(const char *pkcs_name,
- SilcUInt32 key_len_bits,
- const char *pub_filename,
- const char *prv_filename,
- const char *pub_identifier,
- const char *passphrase,
- SilcPKCS *return_pkcs,
- SilcPublicKey *return_public_key,
- SilcPrivateKey *return_private_key,
- SilcBool interactive)
+ SilcUInt32 key_len_bits,
+ const char *pub_filename,
+ const char *prv_filename,
+ const char *pub_identifier,
+ const char *passphrase,
+ SilcPublicKey *return_public_key,
+ SilcPrivateKey *return_private_key,
+ SilcBool interactive)
{
- SilcPKCS pkcs;
- SilcPublicKey pub_key;
- SilcPrivateKey prv_key;
SilcRng rng;
- unsigned char *key;
- SilcUInt32 key_len;
char line[256];
char *pkfile = pub_filename ? strdup(pub_filename) : NULL;
char *prvfile = prv_filename ? strdup(prv_filename) : NULL;
}
}
- if (!silc_pkcs_is_supported(alg)) {
+ if (!silc_pkcs_find_algorithm(alg, NULL)) {
fprintf(stderr, "Unknown PKCS algorithm `%s' or crypto library"
"is not initialized", alg);
return FALSE;
}
/* Generate keys */
- silc_pkcs_alloc(alg, SILC_PKCS_SILC, &pkcs);
- silc_pkcs_generate_key(pkcs, key_len_bits, rng);
+ if (!silc_pkcs_silc_generate_key(alg, "pkcs1-no-oid", key_len_bits,
+ identifier, rng, return_public_key,
+ return_private_key))
+ return FALSE;
/* Save public key into file */
- key = silc_pkcs_get_public_key(pkcs, &key_len);
- pub_key = silc_pkcs_public_key_alloc(silc_pkcs_get_name(pkcs),
- identifier, key, key_len);
- silc_pkcs_save_public_key(pkfile, pub_key, SILC_PKCS_FILE_PEM);
- if (return_public_key)
- *return_public_key = pub_key;
- else
- silc_pkcs_public_key_free(pub_key);
- memset(key, 0, key_len);
- silc_free(key);
+ silc_pkcs_save_public_key(pkfile, *return_public_key, SILC_PKCS_FILE_BASE64);
/* Save private key into file */
- key = silc_pkcs_get_private_key(pkcs, &key_len);
- prv_key = silc_pkcs_private_key_alloc(silc_pkcs_get_name(pkcs),
- key, key_len);
- silc_pkcs_save_private_key(prvfile, prv_key,
- (unsigned char *)pass, strlen(pass),
- SILC_PKCS_FILE_BIN);
- if (return_private_key)
- *return_private_key = prv_key;
- else
- silc_pkcs_private_key_free(prv_key);
- memset(key, 0, key_len);
- silc_free(key);
+ silc_pkcs_save_private_key(prvfile, *return_private_key,
+ (const unsigned char *)pass, strlen(pass),
+ SILC_PKCS_FILE_BIN, rng);
printf("Public key has been saved into `%s'.\n", pkfile);
printf("Private key has been saved into `%s'.\n", prvfile);
getchar();
}
- if (return_pkcs)
- *return_pkcs = pkcs;
- else
- silc_pkcs_free(pkcs);
-
silc_rng_free(rng);
silc_free(alg);
silc_free(pkfile);
/* Load key pair */
SilcBool silc_load_key_pair(const char *pub_filename,
- const char *prv_filename,
- const char *passphrase,
- SilcPKCS *return_pkcs,
- SilcPublicKey *return_public_key,
- SilcPrivateKey *return_private_key)
+ const char *prv_filename,
+ const char *passphrase,
+ SilcPublicKey *return_public_key,
+ SilcPrivateKey *return_private_key)
{
char *pass = passphrase ? strdup(passphrase) : NULL;
SILC_LOG_DEBUG(("Loading public and private keys"));
- if (silc_pkcs_load_public_key((char *)pub_filename, return_public_key,
- SILC_PKCS_FILE_PEM) == FALSE)
- if (silc_pkcs_load_public_key((char *)pub_filename, return_public_key,
- SILC_PKCS_FILE_BIN) == FALSE) {
- if (pass)
- memset(pass, 0, strlen(pass));
- silc_free(pass);
- return FALSE;
- }
+ if (!silc_pkcs_load_public_key(pub_filename, return_public_key)) {
+ if (pass)
+ memset(pass, 0, strlen(pass));
+ silc_free(pass);
+ return FALSE;
+ }
if (!pass) {
pass = silc_get_input("Private key passphrase: ", TRUE);
pass = strdup("");
}
- if (silc_pkcs_load_private_key((char *)prv_filename, return_private_key,
- (unsigned char *)pass, strlen(pass),
- SILC_PKCS_FILE_BIN) == FALSE)
- if (silc_pkcs_load_private_key((char *)prv_filename, return_private_key,
- (unsigned char *)pass, strlen(pass),
- SILC_PKCS_FILE_PEM) == FALSE) {
- memset(pass, 0, strlen(pass));
- silc_free(pass);
- return FALSE;
- }
-
- if (return_pkcs) {
- silc_pkcs_alloc((*return_public_key)->name, SILC_PKCS_SILC, return_pkcs);
- silc_pkcs_public_key_set(*return_pkcs, *return_public_key);
- silc_pkcs_private_key_set(*return_pkcs, *return_private_key);
+ if (!silc_pkcs_load_private_key(prv_filename,
+ (const unsigned char *)pass, strlen(pass),
+ return_private_key)) {
+ memset(pass, 0, strlen(pass));
+ silc_free(pass);
+ return FALSE;
}
memset(pass, 0, strlen(pass));
SilcBool silc_show_public_key(const char *pub_filename)
{
SilcPublicKey public_key;
+ SilcSILCPublicKey silc_pubkey;
SilcPublicKeyIdentifier ident;
char *fingerprint, *babbleprint;
unsigned char *pk;
SilcUInt32 pk_len;
- SilcPKCS pkcs;
SilcUInt32 key_len = 0;
- if (silc_pkcs_load_public_key((char *)pub_filename, &public_key,
- SILC_PKCS_FILE_PEM) == FALSE)
- if (silc_pkcs_load_public_key((char *)pub_filename, &public_key,
- SILC_PKCS_FILE_BIN) == FALSE) {
- fprintf(stderr, "Could not load public key file `%s'\n", pub_filename);
- return FALSE;
- }
+ if (!silc_pkcs_load_public_key((char *)pub_filename, &public_key)) {
+ fprintf(stderr, "Could not load public key file `%s'\n", pub_filename);
+ return FALSE;
+ }
- ident = silc_pkcs_decode_identifier(public_key->identifier);
+ silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
+ if (!silc_pubkey) {
+ silc_pkcs_public_key_free(public_key);
+ return FALSE;
+ }
+ ident = &silc_pubkey->identifier;
+ key_len = silc_pkcs_public_key_get_len(public_key);
pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+ if (!pk) {
+ silc_pkcs_public_key_free(public_key);
+ return FALSE;
+ }
fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
- if (silc_pkcs_alloc(public_key->name, SILC_PKCS_SILC, &pkcs)) {
- key_len = silc_pkcs_public_key_set(pkcs, public_key);
- silc_pkcs_free(pkcs);
- }
-
printf("Public key file : %s\n", pub_filename);
- printf("Algorithm : %s\n", public_key->name);
+ printf("Algorithm : %s\n", silc_pkcs_get_name(public_key));
if (key_len)
printf("Key length (bits) : %d\n", (unsigned int)key_len);
if (ident->realname)
silc_free(babbleprint);
silc_free(pk);
silc_pkcs_public_key_free(public_key);
- silc_pkcs_free_identifier(ident);
return TRUE;
}
/* Change private key passphrase */
SilcBool silc_change_private_key_passphrase(const char *prv_filename,
- const char *old_passphrase,
- const char *new_passphrase)
+ const char *old_passphrase,
+ const char *new_passphrase)
{
SilcPrivateKey private_key;
- SilcBool base64 = FALSE;
char *pass;
+ SilcRng rng;
pass = old_passphrase ? strdup(old_passphrase) : NULL;
if (!pass) {
pass = strdup("");
}
- if (silc_pkcs_load_private_key((char *)prv_filename, &private_key,
- (unsigned char *)pass, strlen(pass),
- SILC_PKCS_FILE_BIN) == FALSE) {
- base64 = TRUE;
- if (silc_pkcs_load_private_key((char *)prv_filename, &private_key,
- (unsigned char *)pass, strlen(pass),
- SILC_PKCS_FILE_PEM) == FALSE) {
- memset(pass, 0, strlen(pass));
- silc_free(pass);
- fprintf(stderr, "Could not load private key `%s' file\n", prv_filename);
- return FALSE;
- }
+ if (!silc_pkcs_load_private_key(prv_filename,
+ (const unsigned char *)pass, strlen(pass),
+ &private_key)) {
+ memset(pass, 0, strlen(pass));
+ silc_free(pass);
+ fprintf(stderr, "Could not load private key `%s' file\n", prv_filename);
+ return FALSE;
}
memset(pass, 0, strlen(pass));
}
}
+ rng = silc_rng_alloc();
+ silc_rng_init(rng);
+
silc_pkcs_save_private_key((char *)prv_filename, private_key,
(unsigned char *)pass, strlen(pass),
- base64 ? SILC_PKCS_FILE_PEM : SILC_PKCS_FILE_BIN);
+ SILC_PKCS_FILE_BIN, rng);
fprintf(stdout, "\nPassphrase changed\n");
silc_free(pass);
silc_pkcs_private_key_free(private_key);
+ silc_rng_free(rng);
+
return TRUE;
}
/*
- silcapputil.h
+ silcapputil.h
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2002 Pekka Riikonen
+ Copyright (C) 2002 - 2005 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
* SYNOPSIS
*
* SilcBool silc_create_key_pair(const char *pkcs_name,
- * SilcUInt32 key_len_bits,
- * const char *pub_filename,
- * const char *prv_filename,
- * const char *pub_identifier,
- * const char *passphrase,
- * SilcPKCS *return_pkcs,
- * SilcPublicKey *return_public_key,
- * SilcPrivateKey *return_private_key,
- * SilcBool interactive);
+ * SilcUInt32 key_len_bits,
+ * const char *pub_filename,
+ * const char *prv_filename,
+ * const char *pub_identifier,
+ * const char *passphrase,
+ * SilcPublicKey *return_public_key,
+ * SilcPrivateKey *return_private_key,
+ * SilcBool interactive);
*
* DESCRIPTION
*
* private key file. It is recommended that you would protect your
* private key file with a passphrase.
*
- * The routine returns FALSE if error occurs during key generation.
- * Function returns TRUE when success and returns the created SilcPKCS
- * object, which can be used to perform public key cryptography into
- * `return_pkcs' pointer, created public key into `return_public_key',
- * and created private key into `return_private_key' pointer.
- *
* If the `interactive' is TRUE then this asks the user (by blocking
* the process for input) some questions about key generation (like
* public key algorithm, key length, filenames, etc). If all
*
***/
SilcBool silc_create_key_pair(const char *pkcs_name,
- SilcUInt32 key_len_bits,
- const char *pub_filename,
- const char *prv_filename,
- const char *pub_identifier,
- const char *passphrase,
- SilcPKCS *return_pkcs,
- SilcPublicKey *return_public_key,
- SilcPrivateKey *return_private_key,
- SilcBool interactive);
+ SilcUInt32 key_len_bits,
+ const char *pub_filename,
+ const char *prv_filename,
+ const char *pub_identifier,
+ const char *passphrase,
+ SilcPublicKey *return_public_key,
+ SilcPrivateKey *return_private_key,
+ SilcBool interactive);
/****f* silcutil/SilcAppUtil/silc_load_key_pair
*
* SYNOPSIS
*
* SilcBool silc_load_key_pair(const char *pub_filename,
- * const char *prv_filename,
- * const char *passphrase,
- * SilcPKCS *return_pkcs,
- * SilcPublicKey *return_public_key,
- * SilcPrivateKey *return_private_key);
+ * const char *prv_filename,
+ * const char *passphrase,
+ * SilcPublicKey *return_public_key,
+ * SilcPrivateKey *return_private_key);
*
* DESCRIPTION
*
* This routine can be used to load the public key and private key
* from files. This retuns FALSE it either of the key could not be
* loaded. This function returns TRUE on success and returns the
- * public key into `return_public_key' pointer, private key into
- * `return_private_key' pointer and the SilcPKCS object to the
- * `return_pkcs'. The SilcPKCS can be used to perform public key
- * cryptographic operations. The `passphrase' is the passphrase
- * which will be used to decrypt the private key file.
+ * public key into `return_public_key' pointer and private key into
+ * `return_private_key'. The `passphrase' is the passphrase which
+ * will be used to decrypt the private key file.
*
***/
SilcBool silc_load_key_pair(const char *pub_filename,
- const char *prv_filename,
- const char *passphrase,
- SilcPKCS *return_pkcs,
- SilcPublicKey *return_public_key,
- SilcPrivateKey *return_private_key);
+ const char *prv_filename,
+ const char *passphrase,
+ SilcPublicKey *return_public_key,
+ SilcPrivateKey *return_private_key);
/****f* silcutil/SilcAppUtil/silc_show_public_key
*
* SYNOPSIS
*
* SilcBool silc_change_private_key_passphrase(const char *prv_filename,
- * const char *old_passphrase,
- * const char *new_passphrase);
+ * const char *old_passphrase,
+ * const char *new_passphrase);
*
* DESCRIPTION
*
*
***/
SilcBool silc_change_private_key_passphrase(const char *prv_filename,
- const char *old_passphrase,
- const char *new_passphrase);
+ const char *old_passphrase,
+ const char *new_passphrase);
#endif /* SILCAPPUTIL_H */
return h;
}
-/* Hashed SILC Public key. */
+/* Hash public key of any type. */
SilcUInt32 silc_hash_public_key(void *key, void *user_context)
{
- SilcPublicKey pk = (SilcPublicKey)key;
- return (pk->len + (silc_hash_string(pk->name, NULL) ^
- silc_hash_string(pk->identifier, NULL) ^
- silc_hash_data(pk->pk, SILC_32_TO_PTR(pk->pk_len))));
+ SilcPublicKey public_key = key;
+ unsigned char *pk;
+ SilcUInt32 pk_len;
+ SilcUInt32 hash = 0;
+
+ pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+ if (!pk)
+ return hash;
+
+ hash = silc_hash_data(pk, SILC_32_TO_PTR(pk_len));
+ silc_free(pk);
+
+ return hash;
}
/* Compares two strings. It may be used as SilcHashTable comparison
/* Compare two Client ID's entirely and not just the hash from the ID. */
-SilcBool silc_hash_client_id_compare(void *key1, void *key2, void *user_context)
+SilcBool silc_hash_client_id_compare(void *key1, void *key2,
+ void *user_context)
{
return SILC_ID_COMPARE_TYPE(key1, key2, SILC_ID_CLIENT);
}
/* Compares two SILC Public keys. It may be used as SilcHashTable
comparison function. */
-SilcBool silc_hash_public_key_compare(void *key1, void *key2, void *user_context)
+SilcBool silc_hash_public_key_compare(void *key1, void *key2,
+ void *user_context)
{
return silc_pkcs_public_key_compare(key1, key2);
}
*
* DESCRIPTION
*
- * Hashed SILC Public key.
+ * Hash public key of any type.
*
***/
SilcUInt32 silc_hash_public_key(void *key, void *user_context);