From 77abbd182dcd2d6915ae10297f2438eadeb2b491 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Fri, 11 Oct 2002 21:02:48 +0000 Subject: [PATCH] Added SILC_SKE_STATUS_SIGNATURE_ERROR and OUT_OF_MEMORY and added better error printing to SKE library. Fixed the usage of silc_pkcs_get_key_len as it returns the length in bits not in bytes. --- lib/silccore/silcauth.c | 2 +- lib/silccrypt/silcpkcs.c | 6 +-- lib/silcske/payload.c | 25 ++++++++--- lib/silcske/silcske.c | 86 +++++++++++++++++++++++------------- lib/silcske/silcske_status.h | 2 + 5 files changed, 82 insertions(+), 39 deletions(-) diff --git a/lib/silccore/silcauth.c b/lib/silccore/silcauth.c index 63ad6940..aea21a99 100644 --- a/lib/silccore/silcauth.c +++ b/lib/silccore/silcauth.c @@ -274,7 +274,7 @@ SilcBuffer silc_auth_public_key_auth_generate(SilcPublicKey public_key, silc_pkcs_private_key_set(pkcs, private_key); /* Compute the hash and the signature. */ - if (silc_pkcs_get_key_len(pkcs) > sizeof(auth_data) - 1 || + 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)) { memset(randomdata, 0, 256); diff --git a/lib/silccrypt/silcpkcs.c b/lib/silccrypt/silcpkcs.c index 2e8ca92e..cbc8c762 100644 --- a/lib/silccrypt/silcpkcs.c +++ b/lib/silccrypt/silcpkcs.c @@ -25,9 +25,9 @@ /* The main SILC PKCS structure. */ struct SilcPKCSStruct { - void *context; - SilcPKCSObject *pkcs; - SilcUInt32 key_len; + void *context; /* Algorithm internal context */ + SilcPKCSObject *pkcs; /* Algorithm implementation */ + SilcUInt32 key_len; /* Key length in bits */ }; #ifndef SILC_EPOC diff --git a/lib/silcske/payload.c b/lib/silcske/payload.c index eafbd873..eeb22f01 100644 --- a/lib/silcske/payload.c +++ b/lib/silcske/payload.c @@ -37,6 +37,8 @@ SilcSKEStatus silc_ske_payload_start_encode(SilcSKE ske, return SILC_SKE_STATUS_ERROR; buf = silc_buffer_alloc(payload->len); + if (!buf) + return SILC_SKE_STATUS_OUT_OF_MEMORY; silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf)); /* Encode the payload */ @@ -99,6 +101,8 @@ silc_ske_payload_start_decode(SilcSKE ske, SILC_LOG_HEXDUMP(("KE Start Payload"), buffer->data, buffer->len); payload = silc_calloc(1, sizeof(*payload)); + if (!payload) + return SILC_SKE_STATUS_OUT_OF_MEMORY; payload->cookie_len = SILC_SKE_COOKIE_LEN; /* Parse start of the payload */ @@ -125,18 +129,20 @@ silc_ske_payload_start_decode(SilcSKE ske, &payload->comp_alg_len), SILC_STR_END); if (ret == -1) { - status = SILC_SKE_STATUS_ERROR; + SILC_LOG_ERROR(("Malformed KE Start Payload")); + status = SILC_SKE_STATUS_BAD_PAYLOAD; goto err; } if (tmp != 0) { SILC_LOG_DEBUG(("Bad reserved field")); + SILC_LOG_ERROR(("Bad RESERVED field in KE Start Payload")); status = SILC_SKE_STATUS_BAD_RESERVED_FIELD; goto err; } if (payload->len != buffer->len) { - SILC_LOG_DEBUG(("Bad payload length")); + SILC_LOG_ERROR(("Garbage after KE Start Payload")); status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH; goto err; } @@ -201,6 +207,8 @@ SilcSKEStatus silc_ske_payload_ke_encode(SilcSKE ske, is 4 + public key + 2 + x + 2 + signature. */ buf = silc_buffer_alloc(4 + payload->pk_len + 2 + x_len + 2 + payload->sign_len); + if (!buf) + return SILC_SKE_STATUS_OUT_OF_MEMORY; silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf)); /* Encode the payload */ @@ -252,6 +260,8 @@ SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske, SILC_LOG_HEXDUMP(("KE Payload"), buffer->data, buffer->len); payload = silc_calloc(1, sizeof(*payload)); + if (!payload) + return SILC_SKE_STATUS_OUT_OF_MEMORY; len2 = buffer->len; @@ -261,13 +271,15 @@ SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske, SILC_STR_UI_SHORT(&payload->pk_type), SILC_STR_END); if (ret == -1) { - status = SILC_SKE_STATUS_ERROR; + SILC_LOG_ERROR(("Cannot decode public key from KE payload")); + status = SILC_SKE_STATUS_BAD_PAYLOAD; goto err; } if (ske->start_payload && (payload->pk_type < SILC_SKE_PK_TYPE_SILC || payload->pk_type > SILC_SKE_PK_TYPE_SPKI)) { + SILC_LOG_ERROR(("Malformed public key in KE payload")); status = SILC_SKE_STATUS_BAD_PAYLOAD; goto err; } @@ -284,7 +296,8 @@ SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske, &payload->sign_len), SILC_STR_END); if (ret == -1) { - status = SILC_SKE_STATUS_ERROR; + SILC_LOG_ERROR(("Malformed KE Payload")); + status = SILC_SKE_STATUS_BAD_PAYLOAD; goto err; } @@ -292,6 +305,7 @@ SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske, tot_len += payload->sign_len + 2; if (x_len < 3) { + SILC_LOG_ERROR(("Too short signature in KE Payload")); status = SILC_SKE_STATUS_BAD_PAYLOAD; goto err; } @@ -299,13 +313,14 @@ SilcSKEStatus silc_ske_payload_ke_decode(SilcSKE ske, if (ske->start_payload && (ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) && (payload->sign_len < 3 || !payload->sign_data)) { - SILC_LOG_DEBUG(("The signature data is missing - both parties are " + SILC_LOG_ERROR(("The signature data is missing - both parties are " "required to do authentication")); status = SILC_SKE_STATUS_BAD_PAYLOAD; goto err; } if (tot_len != len2) { + SILC_LOG_ERROR(("Garbage after KE payload")); status = SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH; goto err; } diff --git a/lib/silcske/silcske.c b/lib/silcske/silcske.c index 6535f55d..625e4110 100644 --- a/lib/silcske/silcske.c +++ b/lib/silcske/silcske.c @@ -50,6 +50,8 @@ SilcSKE silc_ske_alloc(SilcRng rng, void *context) 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; @@ -157,6 +159,8 @@ void silc_ske_set_callbacks(SilcSKE ske, 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; @@ -236,7 +240,7 @@ SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske, /* 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; @@ -262,6 +266,8 @@ SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske, 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) @@ -341,6 +347,10 @@ SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske, /* 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, @@ -356,6 +366,12 @@ SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske, /* 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")); @@ -397,15 +413,15 @@ SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske, /* Sign the hash value */ silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv, private_key->prv_len); - if (silc_pkcs_get_key_len(ske->prop->pkcs) > sizeof(sign) - 1 || + 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 = status; - return status; + 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); @@ -503,7 +519,6 @@ static void silc_ske_initiator_finish_final(SilcSKE ske, payload->sign_len, hash, hash_len) == FALSE) { SILC_LOG_DEBUG(("Signature don't match")); - status = SILC_SKE_STATUS_INCORRECT_SIGNATURE; goto err; } @@ -1015,7 +1030,7 @@ SilcSKEStatus silc_ske_responder_finish(SilcSKE ske, /* 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; @@ -1038,9 +1053,11 @@ SilcSKEStatus silc_ske_responder_finish(SilcSKE ske, /* Sign the hash value */ silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv, private_key->prv_len); - if (silc_pkcs_get_key_len(ske->prop->pkcs) > sizeof(sign) - 1 || - !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)); @@ -1087,8 +1104,9 @@ SilcSKEStatus silc_ske_end(SilcSKE ske) 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); @@ -1115,8 +1133,9 @@ SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status) 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); @@ -1581,7 +1600,7 @@ static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n, /* Get the random number as string */ string = silc_rng_get_rn_data(ske->rng, (len / 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); @@ -1624,11 +1643,12 @@ static SilcSKEStatus silc_ske_make_hash(SilcSKE ske, 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) { @@ -1680,9 +1700,10 @@ static SilcSKEStatus silc_ske_make_hash(SilcSKE ske, } 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 = @@ -1741,8 +1762,9 @@ silc_ske_process_key_material_data(unsigned char *data, 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), @@ -1779,8 +1801,9 @@ silc_ske_process_key_material_data(unsigned char *data, 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), @@ -1839,8 +1862,9 @@ silc_ske_process_key_material_data(unsigned char *data, 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), @@ -1920,8 +1944,9 @@ SilcSKEStatus silc_ske_process_key_material(SilcSKE ske, /* 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), @@ -1992,7 +2017,8 @@ const char *silc_ske_status_string[] = "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 }; diff --git a/lib/silcske/silcske_status.h b/lib/silcske/silcske_status.h index 908a807d..4eb33719 100644 --- a/lib/silcske/silcske_status.h +++ b/lib/silcske/silcske_status.h @@ -63,6 +63,8 @@ typedef enum { SILC_SKE_STATUS_KEY_EXCHANGE_NOT_ACTIVE, /* SKE is not started */ SILC_SKE_STATUS_BAD_RESERVED_FIELD, /* Reserved field was not 0 */ SILC_SKE_STATUS_BAD_PAYLOAD_LENGTH, /* Payload includes garbage */ + SILC_SKE_STATUS_SIGNATURE_ERROR, /* Error computing signature */ + SILC_SKE_STATUS_OUT_OF_MEMORY, /* System out of memory */ /* Other internal status types */ SILC_SKE_STATUS_FREED, /* Internal library status */ -- 2.24.0