/*
- silcpkcs.c
+ silcpkcs.c
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2002 Pekka Riikonen
+ 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
#include "silcincludes.h"
#include "rsa.h"
-#include "pkcs1.h"
/* The main SILC PKCS structure. */
struct SilcPKCSStruct {
const SilcPKCSObject silc_default_pkcs[] =
{
/* RSA with PKCS #1 (Uses directly routines from Raw RSA operations) */
- { "rsa",
+ { "rsa",
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_sign, silc_pkcs1_verify },
/* Raw RSA operations */
- { "rsa-raw",
+ { "rsa-raw",
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,
return FALSE;
}
-/* Function that registers all the default PKCS (all builtin PKCS).
+/* 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. */
while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
len += strlen(entry->name);
list = silc_realloc(list, len + 1);
-
- memcpy(list + (len - strlen(entry->name)),
+
+ memcpy(list + (len - strlen(entry->name)),
entry->name, strlen(entry->name));
memcpy(list + len, ",", 1);
len++;
entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
len += strlen(entry->name);
list = silc_realloc(list, len + 1);
-
- memcpy(list + (len - strlen(entry->name)),
+
+ memcpy(list + (len - strlen(entry->name)),
entry->name, strlen(entry->name));
memcpy(list + len, ",", 1);
len++;
bool silc_pkcs_generate_key(SilcPKCS pkcs, SilcUInt32 bits_key_len,
SilcRng rng)
{
- return pkcs->pkcs->init(pkcs->context, bits_key_len, rng);
+ bool 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 */
SilcUInt32 silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
{
- pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
+ pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
public_key->pk_len);
return pkcs->key_len;
}
SilcUInt32 silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
{
SilcUInt32 key_len;
- key_len = pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
+ 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;
/* Verifies signature */
-bool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
- SilcUInt32 signature_len, unsigned char *data,
+bool 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,
+ return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
data, data_len);
}
/* Verifies signature with hash. The `data' is hashed and verified against
the `signature'. */
-bool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
- unsigned char *signature,
- SilcUInt32 signature_len,
- unsigned char *data,
+bool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
+ unsigned char *signature,
+ SilcUInt32 signature_len,
+ unsigned char *data,
SilcUInt32 data_len)
{
unsigned char hashr[32];
SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
- ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
+ ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
hashr, hash_len);
memset(hashr, 0, sizeof(hashr));
return ret;
}
-/* Encodes and returns SILC public key identifier. If some of the
+/* 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. */
(email ? strlen(email) : 0) +
(org ? strlen(org) : 0) +
(country ? strlen(country) : 0);
-
+
if (len < 3)
return NULL;
SILC_STR_UI32_STRING(username),
SILC_STR_END);
silc_buffer_pull(buf, 3 + strlen(username));
- tlen = 3 + strlen(username);
+ tlen = 3 + strlen(username);
}
-
+
if (host) {
silc_buffer_format(buf,
SILC_STR_UI32_STRING(", "),
SILC_STR_UI32_STRING(host),
SILC_STR_END);
silc_buffer_pull(buf, 5 + strlen(host));
- tlen += 5 + strlen(host);
+ tlen += 5 + strlen(host);
}
if (realname) {
SILC_STR_UI32_STRING(realname),
SILC_STR_END);
silc_buffer_pull(buf, 5 + strlen(realname));
- tlen += 5 + strlen(realname);
+ tlen += 5 + strlen(realname);
}
if (email) {
SILC_STR_UI32_STRING(email),
SILC_STR_END);
silc_buffer_pull(buf, 4 + strlen(email));
- tlen += 4 + strlen(email);
+ tlen += 4 + strlen(email);
}
if (org) {
SILC_STR_UI32_STRING(org),
SILC_STR_END);
silc_buffer_pull(buf, 4 + strlen(org));
- tlen += 4 + strlen(org);
+ tlen += 4 + strlen(org);
}
if (country) {
SILC_STR_UI32_STRING(country),
SILC_STR_END);
silc_buffer_pull(buf, 4 + strlen(country));
- tlen += 4 + strlen(country);
+ tlen += 4 + strlen(country);
}
silc_buffer_push(buf, buf->data - buf->head);
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->org = strdup(item + strcspn(cp, "=") + 1);
else if (strstr(item, "C="))
ident->country = strdup(item + strcspn(cp, "=") + 1);
-
+
cp += len;
- if (strlen(cp) == 0)
+ if (strlen(cp) < 1)
cp = NULL;
else
cp += 1;
-
+
if (item)
silc_free(item);
}
/* Allocates SILC style public key formed from sent arguments. All data
is duplicated. */
-SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
+SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
const char *identifier,
- const unsigned char *pk,
+ const unsigned char *pk,
SilcUInt32 pk_len)
{
SilcPublicKey public_key;
public_key = silc_calloc(1, sizeof(*public_key));
public_key->name = strdup(name);
public_key->pk_len = pk_len;
- public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
+ public_key->pk = silc_memdup(pk, pk_len);
public_key->pk_type = SILC_SKE_PK_TYPE_SILC;
- memcpy(public_key->pk, pk, pk_len);
if (!silc_utf8_valid(identifier, strlen(identifier))) {
int len = silc_utf8_encoded_len(identifier, strlen(identifier), 0);
private_key = silc_calloc(1, sizeof(*private_key));
private_key->name = strdup(name);
private_key->prv_len = prv_len;
- private_key->prv = silc_calloc(prv_len, sizeof(*private_key->prv));
- memcpy(private_key->prv, prv, prv_len);
+ private_key->prv = silc_memdup(prv, prv_len);
return private_key;
}
{
if (private_key) {
silc_free(private_key->name);
- silc_free(private_key->prv);
+ if (private_key->prv) {
+ memset(private_key->prv, 0, private_key->prv_len);
+ silc_free(private_key->prv);
+ }
silc_free(private_key);
}
}
unsigned char *
silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len)
{
- SilcBuffer buf;
- unsigned char *ret;
-
- buf = silc_buffer_alloc(public_key->len + 4);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
-
- silc_buffer_format(buf,
- SILC_STR_UI_INT(public_key->len),
- SILC_STR_UI_SHORT(strlen(public_key->name)),
- SILC_STR_UI32_STRING(public_key->name),
- SILC_STR_UI_SHORT(strlen(public_key->identifier)),
- SILC_STR_UI32_STRING(public_key->identifier),
- SILC_STR_UI_XNSTRING(public_key->pk,
- public_key->pk_len),
- SILC_STR_END);
- if (len)
- *len = public_key->len + 4;
-
- ret = silc_calloc(buf->len, sizeof(*ret));
- memcpy(ret, buf->data, buf->len);
- silc_buffer_free(buf);
-
- return ret;
+ return silc_pkcs_public_key_data_encode(public_key->pk,
+ public_key->pk_len,
+ public_key->name,
+ public_key->identifier, len);
}
/* Encodes SILC style public key. Returns the encoded data. */
unsigned char *
silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
- char *pkcs, char *identifier,
+ char *pkcs, char *identifier,
SilcUInt32 *len)
{
SilcBuffer buf;
SilcUInt32 totlen;
totlen = 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
- buf = silc_buffer_alloc(totlen + 4);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+ buf = silc_buffer_alloc_size(totlen + 4);
+ if (!buf)
+ return NULL;
silc_buffer_format(buf,
SILC_STR_UI_INT(totlen),
SILC_STR_UI32_STRING(identifier),
SILC_STR_UI_XNSTRING(pk, pk_len),
SILC_STR_END);
- if (len)
- *len = totlen + 4;
- ret = silc_calloc(buf->len, sizeof(*ret));
- memcpy(ret, buf->data, buf->len);
+ ret = silc_buffer_steal(buf, len);
silc_buffer_free(buf);
-
return ret;
}
bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
SilcPublicKey *public_key)
{
- SilcBuffer buf;
+ 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;
- buf = silc_buffer_alloc(data_len);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
- silc_buffer_put(buf, data, data_len);
+ silc_buffer_set(&buf, data, data_len);
/* Get length */
- ret = silc_buffer_unformat(buf,
+ ret = silc_buffer_unformat(&buf,
SILC_STR_UI_INT(&totlen),
SILC_STR_END);
- if (ret == -1) {
- silc_buffer_free(buf);
+ if (ret == -1)
return FALSE;
- }
#if 1 /* Backwards support, remove! */
if (totlen == data_len)
totlen -= 4;
#endif
- if (totlen + 4 != data_len) {
- silc_buffer_free(buf);
+ if (totlen + 4 != data_len)
return FALSE;
- }
/* Get algorithm name and identifier */
- silc_buffer_pull(buf, 4);
+ silc_buffer_pull(&buf, 4);
ret =
- silc_buffer_unformat(buf,
+ 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 ||
+ if (pkcs_len < 1 || identifier_len < 3 ||
pkcs_len + identifier_len > totlen)
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 = buf->len;
- ret = silc_buffer_unformat(buf,
+ silc_buffer_pull(&buf, 2 + pkcs_len + 2 + identifier_len);
+ key_len = buf.len;
+ 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.
+ 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, &alg);
goto err;
silc_pkcs_free(alg);
}
-
+
if (public_key) {
*public_key = silc_calloc(1, sizeof(**public_key));
(*public_key)->len = totlen;
(*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
}
- silc_buffer_free(buf);
return TRUE;
err:
- if (pkcs_name)
- silc_free(pkcs_name);
- if (ident)
- silc_free(ident);
- if (key_data)
- silc_free(key_data);
- silc_buffer_free(buf);
+ silc_free(pkcs_name);
+ silc_free(ident);
+ silc_free(key_data);
return FALSE;
}
if (!public_key)
return FALSE;
-#if 1
- /* XXX 1.1 version support. Check whether the data is actually raw
- public key and attempt to decode. Remove this later! */
- if (silc_pkcs_public_key_decode(data, data_len, public_key)) {
- (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
- return TRUE;
- }
-#endif
-
silc_buffer_set(&buf, data, data_len);
ret = silc_buffer_unformat(&buf,
SILC_STR_UI_SHORT(&pk_len),
unsigned char *
silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
{
- SilcBuffer buf;
- unsigned char *ret;
- SilcUInt32 totlen;
-
- totlen = 2 + strlen(private_key->name) + private_key->prv_len;
- buf = silc_buffer_alloc(totlen);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
-
- silc_buffer_format(buf,
- SILC_STR_UI_SHORT(strlen(private_key->name)),
- SILC_STR_UI32_STRING(private_key->name),
- SILC_STR_UI_XNSTRING(private_key->prv,
- private_key->prv_len),
- SILC_STR_END);
- if (len)
- *len = totlen;
-
- ret = silc_calloc(buf->len, sizeof(*ret));
- memcpy(ret, buf->data, buf->len);
- silc_buffer_clear(buf);
- silc_buffer_free(buf);
-
- return ret;
+ 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. */
SilcUInt32 totlen;
totlen = 2 + strlen(pkcs) + prv_len;
- buf = silc_buffer_alloc(totlen);
- silc_buffer_pull_tail(buf, totlen);
+ 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);
- if (len)
- *len = totlen;
- ret = silc_calloc(buf->len, sizeof(*ret));
- memcpy(ret, buf->data, buf->len);
- silc_buffer_clear(buf);
+ ret = silc_buffer_steal(buf, len);
silc_buffer_free(buf);
-
return ret;
}
bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
SilcPrivateKey *private_key)
{
- SilcBuffer buf;
+ SilcBufferStruct buf;
SilcPKCS alg;
SilcUInt16 pkcs_len;
SilcUInt32 key_len;
unsigned char *pkcs_name = NULL, *key_data = NULL;
int ret;
- buf = silc_buffer_alloc(data_len);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
- silc_buffer_put(buf, data, data_len);
+ silc_buffer_set(&buf, data, data_len);
/* Get algorithm name and identifier */
- ret =
- silc_buffer_unformat(buf,
+ ret =
+ silc_buffer_unformat(&buf,
SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
SILC_STR_END);
if (ret == -1) {
goto err;
}
- if (pkcs_len < 1 || pkcs_len > buf->truelen) {
+ if (pkcs_len < 1 || pkcs_len > buf.truelen) {
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);
- key_len = buf->len;
- ret = silc_buffer_unformat(buf,
+ silc_buffer_pull(&buf, 2 + pkcs_len);
+ key_len = buf.len;
+ 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.
+ 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, &alg);
}
silc_pkcs_free(alg);
}
-
+
if (private_key) {
*private_key = silc_calloc(1, sizeof(**private_key));
(*private_key)->name = pkcs_name;
(*private_key)->prv_len = key_len;
}
- silc_buffer_clear(buf);
- silc_buffer_free(buf);
return TRUE;
err:
- if (pkcs_name)
- silc_free(pkcs_name);
- if (key_data)
- silc_free(key_data);
- silc_buffer_clear(buf);
- silc_buffer_free(buf);
+ silc_free(pkcs_name);
+ silc_free(key_data);
return FALSE;
}
/* Internal routine to save public key */
-static bool silc_pkcs_save_public_key_internal(char *filename,
+static bool silc_pkcs_save_public_key_internal(const char *filename,
unsigned char *data,
SilcUInt32 data_len,
SilcUInt32 encoding)
{
SilcBuffer buf;
SilcUInt32 len;
+ unsigned char *tmp = NULL;
switch(encoding) {
case SILC_PKCS_FILE_BIN:
break;
case SILC_PKCS_FILE_PEM:
- data = silc_pem_encode_file(data, data_len);
+ tmp = data = silc_pem_encode_file(data, data_len);
data_len = strlen(data);
break;
}
len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
- buf = silc_buffer_alloc(len);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+ buf = silc_buffer_alloc_size(len);
+ if (!buf) {
+ silc_free(tmp);
+ return FALSE;
+ }
silc_buffer_format(buf,
SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
/* Save into file */
if (silc_file_writefile(filename, buf->data, buf->len)) {
+ silc_free(tmp);
silc_buffer_free(buf);
return FALSE;
}
+ silc_free(tmp);
silc_buffer_free(buf);
return TRUE;
}
/* Saves public key into file */
-bool silc_pkcs_save_public_key(char *filename, SilcPublicKey public_key,
+bool silc_pkcs_save_public_key(const char *filename, SilcPublicKey public_key,
SilcUInt32 encoding)
{
unsigned char *data;
/* Saves public key into file */
-bool silc_pkcs_save_public_key_data(char *filename, unsigned char *data,
- SilcUInt32 data_len,
- SilcUInt32 encoding)
+bool 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);
/* Internal routine to save private key. */
-static bool silc_pkcs_save_private_key_internal(char *filename,
+static bool silc_pkcs_save_private_key_internal(const char *filename,
unsigned char *data,
SilcUInt32 data_len,
unsigned char *key,
SilcUInt32 encoding)
{
SilcCipher aes;
- SilcHash md5;
+ SilcHash sha1;
SilcHmac sha1hmac;
SilcBuffer buf, enc;
- SilcUInt32 len, blocklen;
- unsigned char tmp[32], keymat[32];
+ SilcUInt32 len, blocklen, padlen;
+ unsigned char tmp[32], keymat[64];
int i;
memset(tmp, 0, sizeof(tmp));
if (blocklen * 2 > sizeof(tmp))
return FALSE;
- /* Allocate MD5 hash */
- if (!silc_hash_alloc("md5", &md5)) {
- SILC_LOG_ERROR(("Could not allocate MD5 hash, probably not registered"));
+ /* 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(md5);
+ silc_hash_free(sha1);
silc_cipher_free(aes);
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
+ 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(md5);
- silc_hash_update(md5, key, key_len);
- silc_hash_final(md5, keymat);
- silc_hash_init(md5);
- silc_hash_update(md5, key, key_len);
- silc_hash_update(md5, keymat, 16);
- silc_hash_final(md5, keymat + 16);
+ 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, sizeof(keymat) * 8);
+ 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);
- enc = silc_buffer_alloc_size(data_len + 4 + 4 +
- (blocklen + (data_len % blocklen)) + len);
+ 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(md5);
+ silc_hash_free(sha1);
silc_cipher_free(aes);
return FALSE;
}
/* Generate padding */
- for (i = 0; i < blocklen + (data_len % blocklen); i++)
+ for (i = 0; i < padlen; i++)
tmp[i] = silc_rng_global_get_byte_fast();
/* Put magic number */
silc_buffer_format(enc,
SILC_STR_UI_INT(data_len),
SILC_STR_UI_XNSTRING(data, data_len),
- SILC_STR_UI_XNSTRING(tmp, blocklen + (data_len %
- blocklen)),
+ SILC_STR_UI_XNSTRING(tmp, padlen),
SILC_STR_END);
/* Encrypt. */
memset(keymat, 0, sizeof(keymat));
memset(tmp, 0, sizeof(tmp));
silc_hmac_free(sha1hmac);
- silc_hash_free(md5);
+ silc_hash_free(sha1);
silc_cipher_free(aes);
data = enc->data;
/* Saves private key into file. */
-bool silc_pkcs_save_private_key(char *filename, SilcPrivateKey private_key,
+bool silc_pkcs_save_private_key(const char *filename,
+ SilcPrivateKey private_key,
unsigned char *passphrase,
SilcUInt32 passphrase_len,
SilcUInt32 encoding)
/* Loads public key from file and allocates new public key. Returns TRUE
if loading was successful. */
-bool silc_pkcs_load_public_key(char *filename, SilcPublicKey *public_key,
+bool 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);
if (!data)
return FALSE;
data = silc_pem_decode(data, len, &len);
memset(old, 0, data_len);
silc_free(old);
- old = data;
+ old = data;
data_len = len;
break;
}
/* Load private key from file and allocates new private key. Returns TRUE
if loading was successful. */
-bool silc_pkcs_load_private_key(char *filename, SilcPrivateKey *private_key,
+bool silc_pkcs_load_private_key(const char *filename,
+ SilcPrivateKey *private_key,
unsigned char *passphrase,
SilcUInt32 passphrase_len,
SilcUInt32 encoding)
{
SilcCipher aes;
- SilcHash md5;
+ SilcHash sha1;
SilcHmac sha1hmac;
SilcUInt32 blocklen;
- unsigned char tmp[32], keymat[32];
+ 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)
return FALSE;
return FALSE;
}
- /* Allocate MD5 hash */
- if (!silc_hash_alloc("md5", &md5)) {
- SILC_LOG_ERROR(("Could not allocate MD5 hash, probably not registered"));
+ /* 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);
/* 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(md5);
+ silc_hash_free(sha1);
silc_cipher_free(aes);
memset(old, 0, data_len);
silc_free(old);
}
/* Derive the decryption key from the provided key material. The key
- is 256 bits length, and derived by taking hash of the data, then
+ 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(md5);
- silc_hash_update(md5, passphrase, passphrase_len);
- silc_hash_final(md5, keymat);
- silc_hash_init(md5);
- silc_hash_update(md5, passphrase, passphrase_len);
- silc_hash_update(md5, keymat, 16);
- silc_hash_final(md5, keymat + 16);
+ 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, sizeof(keymat) * 8);
+ silc_cipher_set_key(aes, keymat, 256);
/* First, verify the MAC of the private key data */
mac_len = silc_hmac_len(sha1hmac);
memset(keymat, 0, sizeof(keymat));
memset(tmp, 0, sizeof(tmp));
silc_hmac_free(sha1hmac);
- silc_hash_free(md5);
+ silc_hash_free(sha1);
silc_cipher_free(aes);
memset(old, 0, data_len);
silc_free(old);
len -= 4;
/* Decrypt the private key buffer */
- silc_cipher_decrypt(aes, data, data, len - mac_len, silc_cipher_get_iv(aes));
+ 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(md5);
+ silc_hash_free(sha1);
silc_cipher_free(aes);
memset(old, 0, data_len);
silc_free(old);
memset(keymat, 0, sizeof(keymat));
memset(tmp, 0, sizeof(tmp));
silc_hmac_free(sha1hmac);
- silc_hash_free(md5);
+ silc_hash_free(sha1);
silc_cipher_free(aes);
/* Now decode the actual private key */