Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2002 - 2002 Pekka Riikonen
+ Copyright (C) 2000 - 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
SILC_LOG_DEBUG(("Allocating new Key Exchange object"));
ske = silc_calloc(1, sizeof(*ske));
+ if (!ske)
+ return NULL;
ske->status = SILC_SKE_STATUS_OK;
ske->rng = rng;
ske->user_data = context;
if (ske->callbacks)
silc_free(ske->callbacks);
ske->callbacks = silc_calloc(1, sizeof(*ske->callbacks));
+ if (!ske->callbacks)
+ return;
ske->callbacks->send_packet = send_packet;
ske->callbacks->payload_receive = payload_receive;
ske->callbacks->verify_key = verify_key;
/* Check that the cookie is returned unmodified */
if (memcmp(ske->start_payload->cookie, payload->cookie,
ske->start_payload->cookie_len)) {
- SILC_LOG_DEBUG(("Responder modified our cookie and it must not do it"));
+ SILC_LOG_ERROR(("Responder modified our cookie and it must not do it"));
ske->status = SILC_SKE_STATUS_INVALID_COOKIE;
silc_ske_payload_start_free(ske->start_payload);
return status;
exchange. The same data is returned to upper levels by calling
the callback function. */
ske->prop = prop = silc_calloc(1, sizeof(*prop));
+ if (!ske->prop)
+ goto err;
prop->flags = payload->flags;
status = silc_ske_group_get_by_name(payload->ke_grp_list, &group);
if (status != SILC_SKE_STATUS_OK)
/* Create the random number x, 1 < x < q. */
x = silc_calloc(1, sizeof(*x));
+ if (!x){
+ ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
+ return ske->status;
+ }
silc_mp_init(x);
status =
silc_ske_create_rnd(ske, &ske->prop->group->group_order,
/* Encode the result to Key Exchange Payload. */
payload = silc_calloc(1, sizeof(*payload));
+ if (!payload) {
+ silc_mp_uninit(x);
+ silc_free(x);
+ ske->status = SILC_SKE_STATUS_OUT_OF_MEMORY;
+ return ske->status;
+ }
ske->ke1_payload = payload;
SILC_LOG_DEBUG(("Computing e = g ^ x mod p"));
/* Compute signature data if we are doing mutual authentication */
if (private_key && ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
- unsigned char hash[32], sign[1024];
+ unsigned char hash[32], sign[2048];
SilcUInt32 hash_len, sign_len;
SILC_LOG_DEBUG(("We are doing mutual authentication"));
/* Sign the hash value */
silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
private_key->prv_len);
- silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_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)) {
+ silc_mp_uninit(x);
+ silc_free(x);
+ silc_mp_uninit(&payload->x);
+ silc_free(payload->pk_data);
+ silc_free(payload);
+ ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
+ return ske->status;
+ }
payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
memcpy(payload->sign_data, sign, sign_len);
memset(sign, 0, sizeof(sign));
if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
&public_key)) {
status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
+ SILC_LOG_ERROR(("Unsupported/malformed public key received"));
if (ske->callbacks->proto_continue)
ske->callbacks->proto_continue(ske, ske->callbacks->context);
return;
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) {
-
- SILC_LOG_DEBUG(("Signature don't match"));
-
+ SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
goto err;
}
recv_payload->pk_len,
&public_key)) {
ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
+ SILC_LOG_ERROR(("Unsupported/malformed public key received"));
if (ske->callbacks->proto_continue)
ske->callbacks->proto_continue(ske, ske->callbacks->context);
return;
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) {
-
- SILC_LOG_DEBUG(("Signature don't match"));
-
+ SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
if (ske->callbacks->proto_continue)
ske->callbacks->proto_continue(ske, ske->callbacks->context);
SILC_LOG_DEBUG(("We are doing mutual authentication"));
if (!recv_payload->pk_data && ske->callbacks->verify_key) {
- SILC_LOG_DEBUG(("Remote end did not send its public key (or "
+ SILC_LOG_ERROR(("Remote end did not send its public key (or "
"certificate), even though we require it"));
ske->status = SILC_SKE_STATUS_PUBLIC_KEY_NOT_PROVIDED;
return status;
SilcSKEStatus status = SILC_SKE_STATUS_OK;
SilcBuffer payload_buf;
SilcMPInt *KEY;
- unsigned char hash[32], sign[1024], *pk;
+ unsigned char hash[32], sign[2048], *pk;
SilcUInt32 hash_len, sign_len, pk_len;
SILC_LOG_DEBUG(("Start"));
/* Get the public key */
pk = silc_pkcs_public_key_encode(public_key, &pk_len);
if (!pk) {
- status = SILC_SKE_STATUS_ERROR;
+ status = SILC_SKE_STATUS_OUT_OF_MEMORY;
goto err;
}
ske->ke2_payload->pk_data = pk;
/* Sign the hash value */
silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
private_key->prv_len);
- silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_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)) {
+ status = SILC_SKE_STATUS_SIGNATURE_ERROR;
+ goto err;
+ }
ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
memcpy(ske->ke2_payload->sign_data, sign, sign_len);
memset(sign, 0, sizeof(sign));
SILC_LOG_DEBUG(("Start"));
- packet = silc_buffer_alloc(4);
- silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
+ packet = silc_buffer_alloc_size(4);
+ if (!packet)
+ return SILC_SKE_STATUS_OUT_OF_MEMORY;
silc_buffer_format(packet,
SILC_STR_UI_INT((SilcUInt32)SILC_SKE_STATUS_OK),
SILC_STR_END);
if (status > SILC_SKE_STATUS_INVALID_COOKIE)
status = SILC_SKE_STATUS_BAD_PAYLOAD;
- packet = silc_buffer_alloc(4);
- silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
+ packet = silc_buffer_alloc_size(4);
+ if (!packet)
+ return SILC_SKE_STATUS_OUT_OF_MEMORY;
silc_buffer_format(packet,
SILC_STR_UI_INT((SilcUInt32)status),
SILC_STR_END);
SILC_LOG_DEBUG(("Creating random number"));
/* Get the random number as string */
- string = silc_rng_get_rn_data(ske->rng, (len / 8));
+ string = silc_rng_get_rn_data(ske->rng, ((len - 1) / 8));
if (!string)
- return SILC_SKE_STATUS_ERROR;
+ return SILC_SKE_STATUS_OUT_OF_MEMORY;
/* Decode the string into a MP integer */
- silc_mp_bin2mp(string, (len / 8), rnd);
+ silc_mp_bin2mp(string, ((len - 1) / 8), rnd);
silc_mp_mod_2exp(rnd, rnd, len);
/* Checks */
if (silc_mp_cmp_ui(rnd, 1) < 0)
status = SILC_SKE_STATUS_ERROR;
-
if (silc_mp_cmp(rnd, n) >= 0)
status = SILC_SKE_STATUS_ERROR;
KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
/* Format the buffer used to compute the hash value */
- buf = silc_buffer_alloc(ske->start_payload_copy->len +
- ske->ke2_payload->pk_len +
- ske->ke1_payload->pk_len +
- e_len + f_len + KEY_len);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+ buf = silc_buffer_alloc_size(ske->start_payload_copy->len +
+ ske->ke2_payload->pk_len +
+ ske->ke1_payload->pk_len +
+ e_len + f_len + KEY_len);
+ if (!buf)
+ return SILC_SKE_STATUS_OUT_OF_MEMORY;
/* Initiator is not required to send its public key */
if (!ske->ke1_payload->pk_data) {
} else {
e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
- buf = silc_buffer_alloc(ske->start_payload_copy->len +
- ske->ke1_payload->pk_len + e_len);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+ buf = silc_buffer_alloc_size(ske->start_payload_copy->len +
+ ske->ke1_payload->pk_len + e_len);
+ if (!buf)
+ return SILC_SKE_STATUS_OUT_OF_MEMORY;
/* Format the buffer used to compute the hash value */
ret =
/* Make the hash */
silc_hash_make(ske->prop->hash, buf->data, buf->len, return_hash);
- *return_hash_len = ske->prop->hash->hash->hash_len;
+ *return_hash_len = silc_hash_len(ske->prop->hash);
if (initiator == FALSE) {
SILC_LOG_HEXDUMP(("HASH"), return_hash, *return_hash_len);
if (!req_iv_len || !req_enc_key_len || !req_hmac_key_len)
return SILC_SKE_STATUS_ERROR;
- buf = silc_buffer_alloc(1 + data_len);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+ buf = silc_buffer_alloc_size(1 + data_len);
+ if (!buf)
+ return SILC_SKE_STATUS_OUT_OF_MEMORY;
silc_buffer_format(buf,
SILC_STR_UI_CHAR(0),
SILC_STR_UI_XNSTRING(data, data_len),
silc_hash_make(hash, buf->data, buf->len, k1);
/* Take second round */
- dist = silc_buffer_alloc(data_len + hash_len);
- silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
+ dist = silc_buffer_alloc_size(data_len + hash_len);
+ if (!dist)
+ return SILC_SKE_STATUS_OUT_OF_MEMORY;
silc_buffer_format(dist,
SILC_STR_UI_XNSTRING(data, data_len),
SILC_STR_UI_XNSTRING(k1, hash_len),
memset(k2, 0, sizeof(k2));
memset(k3, 0, sizeof(k3));
silc_free(dtmp);
+ silc_buffer_clear(dist);
silc_buffer_free(dist);
} else {
/* Take normal hash as key */
silc_hash_make(hash, buf->data, buf->len, k1);
/* Take second round */
- dist = silc_buffer_alloc(data_len + hash_len);
- silc_buffer_pull_tail(dist, SILC_BUFFER_END(dist));
+ dist = silc_buffer_alloc_size(data_len + hash_len);
+ if (!dist)
+ return SILC_SKE_STATUS_OUT_OF_MEMORY;
silc_buffer_format(dist,
SILC_STR_UI_XNSTRING(data, data_len),
SILC_STR_UI_XNSTRING(k1, hash_len),
memset(k2, 0, sizeof(k2));
memset(k3, 0, sizeof(k3));
silc_free(dtmp);
+ silc_buffer_clear(dist);
silc_buffer_free(dist);
} else {
/* Take normal hash as key */
key->hmac_key_len = req_hmac_key_len;
memset(hashd, 0, sizeof(hashd));
+ silc_buffer_clear(buf);
silc_buffer_free(buf);
return SILC_SKE_STATUS_OK;
/* Encode KEY to binary data */
tmpbuf = silc_mp_mp2bin(ske->KEY, 0, &klen);
- buf = silc_buffer_alloc(klen + ske->hash_len);
- silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+ buf = silc_buffer_alloc_size(klen + ske->hash_len);
+ if (!buf)
+ return SILC_SKE_STATUS_OUT_OF_MEMORY;
silc_buffer_format(buf,
SILC_STR_UI_XNSTRING(tmpbuf, klen),
SILC_STR_UI_XNSTRING(ske->hash, ske->hash_len),
memset(tmpbuf, 0, klen);
silc_free(tmpbuf);
+ silc_buffer_clear(buf);
silc_buffer_free(buf);
return status;
"Key exchange protocol is not active",
"Bad reserved field in packet",
"Bad payload length in packet",
- "Incorrect hash",
+ "Error computing signature",
+ "System out of memory",
NULL
};