/*
- silcpkcs.c
+ silcpkcs.c
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2001 Pekka Riikonen
+ Copyright (C) 1997 - 2002 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; either version 2 of the License, or
- (at your option) any later version.
-
+ 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
#include "rsa.h"
#include "pkcs1.h"
+/* The main SILC PKCS structure. */
+struct SilcPKCSStruct {
+ void *context;
+ SilcPKCSObject *pkcs;
+ SilcUInt32 key_len;
+};
+
+#ifndef SILC_EPOC
/* Dynamically registered list of PKCS. */
SilcDList silc_pkcs_list = NULL;
+#define SILC_PKCS_LIST silc_pkcs_list
+#else
+#define SILC_PKCS_LIST TRUE
+#endif /* SILC_EPOC */
/* Static list of PKCS for silc_pkcs_register_default(). */
-SilcPKCSObject silc_default_pkcs[] =
+const SilcPKCSObject silc_default_pkcs[] =
{
/* RSA with PKCS #1 (Uses directly routines from Raw RSA operations) */
{ "rsa",
/* Register a new PKCS into SILC. This is used at the initialization of
the SILC. */
-bool silc_pkcs_register(SilcPKCSObject *pkcs)
+bool silc_pkcs_register(const SilcPKCSObject *pkcs)
{
+#ifndef SILC_EPOC
SilcPKCSObject *new;
SILC_LOG_DEBUG(("Registering new PKCS `%s'", pkcs->name));
+ /* 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))
+ return FALSE;
+ }
+ }
+
new = silc_calloc(1, sizeof(*new));
new->name = strdup(pkcs->name);
new->init = pkcs->init;
silc_pkcs_list = silc_dlist_init();
silc_dlist_add(silc_pkcs_list, new);
+#endif /* SILC_EPOC */
return TRUE;
}
bool silc_pkcs_unregister(SilcPKCSObject *pkcs)
{
+#ifndef SILC_EPOC
SilcPKCSObject *entry;
SILC_LOG_DEBUG(("Unregistering PKCS"));
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) {
silc_dlist_uninit(silc_pkcs_list);
}
}
+#endif /* SILC_EPOC */
return FALSE;
}
bool silc_pkcs_register_default(void)
{
+#ifndef SILC_EPOC
int i;
for (i = 0; silc_default_pkcs[i].name; i++)
silc_pkcs_register(&(silc_default_pkcs[i]));
+#endif /* SILC_EPOC */
+ return TRUE;
+}
+
+bool silc_pkcs_unregister_all(void)
+{
+#ifndef SILC_EPOC
+ SilcPKCSObject *entry;
+
+ if (!silc_pkcs_list)
+ 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;
+ }
+#endif /* SILC_EPOC */
return TRUE;
}
bool silc_pkcs_alloc(const unsigned char *name, SilcPKCS *new_pkcs)
{
- SilcPKCSObject *entry;
+ SilcPKCSObject *entry = NULL;
SILC_LOG_DEBUG(("Allocating new PKCS object"));
+#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)) {
- *new_pkcs = silc_calloc(1, sizeof(**new_pkcs));
- (*new_pkcs)->pkcs = entry;
- (*new_pkcs)->context = silc_calloc(1, entry->context_len());
- (*new_pkcs)->get_key_len = silc_pkcs_get_key_len;
- return TRUE;
+ if (!strcmp(entry->name, name))
+ 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)) {
+ entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
+ break;
}
}
}
+#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 FALSE;
}
int silc_pkcs_is_supported(const unsigned char *name)
{
+#ifndef SILC_EPOC
SilcPKCSObject *entry;
if (silc_pkcs_list) {
return TRUE;
}
}
-
+#else
+ {
+ int i;
+ for (i = 0; silc_default_pkcs[i].name; i++)
+ if (!strcmp(silc_default_pkcs[i].name, name))
+ return TRUE;
+ }
+#endif /* SILC_EPOC */
return FALSE;
}
{
SilcPKCSObject *entry;
char *list = NULL;
- int len;
+ int len = 0;
- 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) {
memcpy(list + len, ",", 1);
len++;
}
- list[len - 1] = 0;
}
+#else
+ {
+ int i;
+ for (i = 0; silc_default_pkcs[i].name; i++) {
+ entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
+ len += strlen(entry->name);
+ list = silc_realloc(list, len + 1);
+
+ memcpy(list + (len - strlen(entry->name)),
+ entry->name, strlen(entry->name));
+ memcpy(list + len, ",", 1);
+ len++;
+ }
+ }
+#endif /* SILC_EPOC */
+
+ list[len - 1] = 0;
return list;
}
+/* Generate new key pair into the `pkcs' context. */
+
+int silc_pkcs_generate_key(SilcPKCS pkcs, SilcUInt32 bits_key_len,
+ SilcRng rng)
+{
+ return pkcs->pkcs->init(pkcs->context, bits_key_len, rng);
+}
+
/* Returns the length of the key */
SilcUInt32 silc_pkcs_get_key_len(SilcPKCS pkcs)
return pkcs->key_len;
}
+const char *silc_pkcs_get_name(SilcPKCS pkcs)
+{
+ return pkcs->pkcs->name;
+}
+
/* Returns SILC style public key */
unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, SilcUInt32 *len)
int ret;
silc_hash_make(hash, src, src_len, hashr);
- hash_len = hash->hash->hash_len;
+ hash_len = silc_hash_len(hash);
SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
int ret;
silc_hash_make(hash, data, data_len, hashr);
- hash_len = hash->hash->hash_len;
+ hash_len = silc_hash_len(hash);
SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
/* Allocates SILC style public key formed from sent arguments. All data
is duplicated. */
-SilcPublicKey silc_pkcs_public_key_alloc(char *name, char *identifier,
- unsigned char *pk,
+SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
+ const char *identifier,
+ const unsigned char *pk,
SilcUInt32 pk_len)
{
SilcPublicKey public_key;
+ char *tmp = NULL;
public_key = silc_calloc(1, sizeof(*public_key));
- public_key->len = 4 + 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
public_key->name = strdup(name);
- public_key->identifier = strdup(identifier);
public_key->pk_len = pk_len;
public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
memcpy(public_key->pk, pk, pk_len);
+ 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 = 4 + 2 + strlen(name) + 2 + strlen(identifier) + pk_len;
+ silc_free(tmp);
+
return public_key;
}
/* Allocates SILC private key formed from sent arguments. All data is
duplicated. */
-SilcPrivateKey silc_pkcs_private_key_alloc(char *name, unsigned char *prv,
+SilcPrivateKey silc_pkcs_private_key_alloc(const char *name,
+ const unsigned char *prv,
SilcUInt32 prv_len)
{
SilcPrivateKey private_key;
goto err;
/* See if we support this algorithm (check only if PKCS are registered) */
- if (silc_pkcs_list && !silc_pkcs_is_supported(pkcs_name)) {
+ if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
SILC_LOG_DEBUG(("Unknown PKCS %s", pkcs_name));
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) {
+ if (SILC_PKCS_LIST) {
silc_pkcs_alloc(pkcs_name, &alg);
if (!alg->pkcs->set_public_key(alg->context, key_data, key_len))
goto err;
return FALSE;
}
+/* Copies the public key indicated by `public_key' and returns new allocated
+ public key which is indentical to the `public_key'. */
+
+SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
+{
+ SilcPublicKey key = silc_calloc(1, sizeof(*key));
+ 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;
+
+ return key;
+}
+
/* Encodes SILC private key from SilcPrivateKey. Returns the encoded data. */
unsigned char *
goto err;
/* See if we support this algorithm (check only if PKCS are registered). */
- if (silc_pkcs_list && !silc_pkcs_is_supported(pkcs_name)) {
+ if (SILC_PKCS_LIST && !silc_pkcs_is_supported(pkcs_name)) {
SILC_LOG_DEBUG(("Unknown PKCS `%s'", pkcs_name));
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) {
+ if (SILC_PKCS_LIST) {
silc_pkcs_alloc(pkcs_name, &alg);
if (!alg->pkcs->set_private_key(alg->context, key_data, key_len))
goto err;
case SILC_PKCS_FILE_BIN:
break;
case SILC_PKCS_FILE_PEM:
- data = silc_encode_pem_file(data, data_len);
+ data = silc_pem_encode_file(data, data_len);
data_len = strlen(data);
break;
}
case SILC_PKCS_FILE_BIN:
break;
case SILC_PKCS_FILE_PEM:
- data = silc_encode_pem_file(data, data_len);
+ data = silc_pem_encode_file(data, data_len);
data_len = strlen(data);
break;
}
case SILC_PKCS_FILE_BIN:
break;
case SILC_PKCS_FILE_PEM:
- data = silc_decode_pem(data, len, &len);
+ data = silc_pem_decode(data, len, &len);
memset(old, 0, data_len);
silc_free(old);
old = data;
case SILC_PKCS_FILE_BIN:
break;
case SILC_PKCS_FILE_PEM:
- data = silc_decode_pem(data, len, &len);
+ data = silc_pem_decode(data, len, &len);
break;
}