From: Pekka Riikonen Date: Sun, 22 Jul 2007 08:17:22 +0000 (+0000) Subject: Fixed SSH2 DSS signature decoding. X-Git-Tag: 1.2.beta1~151 X-Git-Url: http://git.silcnet.org/gitweb/?p=crypto.git;a=commitdiff_plain;h=7070c1fb2d65e8c6c4765404939c58fa1f94eb62 Fixed SSH2 DSS signature decoding. --- diff --git a/lib/silccrypt/DIRECTORY b/lib/silccrypt/DIRECTORY index 4a777cd5..67556b69 100644 --- a/lib/silccrypt/DIRECTORY +++ b/lib/silccrypt/DIRECTORY @@ -1,14 +1,14 @@ SILC Crypto Library diff --git a/lib/silcssh/silcssh.h b/lib/silcssh/silcssh.h index acc98929..6c52bc7a 100644 --- a/lib/silcssh/silcssh.h +++ b/lib/silcssh/silcssh.h @@ -53,12 +53,12 @@ * * // Save new key pair to file * silc_pkcs_save_public_key("pubkey.pub", public_key, SILC_PKCS_FILE_BASE64); - * silc_pkcs_save_private_key("privkey.pub", private_key, passphrase, + * silc_pkcs_save_private_key("privkey.prv", private_key, passphrase, * passphrase_len, SILC_PKCS_FILE_BASE64, rng); * * // Load SSH2 key pair * silc_pkcs_load_public_key("pubkey.pub", SILC_PKCS_SSH2, &public_key); - * silc_pkcs_load_private_key("privkey.pub", passphrase, passphrase_len, + * silc_pkcs_load_private_key("privkey.prv", passphrase, passphrase_len, * SILC_PKCS_SSH2, &public_key); * * // Free public and private key. Frees automatically the underlaying SSH keys. diff --git a/lib/silcssh/silcssh_pkcs.c b/lib/silcssh/silcssh_pkcs.c index 4b370de6..248aead7 100644 --- a/lib/silcssh/silcssh_pkcs.c +++ b/lib/silcssh/silcssh_pkcs.c @@ -952,7 +952,7 @@ SILC_PKCS_SIGN(silc_pkcs_ssh_sign) return NULL; } - stack = silc_stack_alloc(2048, silc_crypto_stack()); + stack = silc_stack_alloc(0, silc_crypto_stack()); sign = silc_scalloc(stack, 1, sizeof(*sign)); if (!sign) { @@ -978,29 +978,81 @@ SILC_PKCS_SIGN(silc_pkcs_ssh_sign) SILC_PKCS_VERIFY(silc_pkcs_ssh_verify) { SilcSshPublicKey pubkey = public_key; - SilcBufferStruct sig; + SilcAsyncOperation op; + SilcBufferStruct sig, r, s; + unsigned char *signame; + SilcStack stack = NULL; + SilcAsn1 asn1; if (!pubkey->pkcs->verify) { verify_cb(FALSE, context); return NULL; } - /* Decode the SSH2 protocol style signature encoding. Ignore the - algorithm name. We know the algorithm. */ + /* Decode the SSH2 protocol style signature encoding. */ silc_buffer_set(&sig, signature, signature_len); if (silc_buffer_unformat(&sig, - SILC_STR_UI32_NSTRING(NULL, NULL), + SILC_STR_UI32_STRING_ALLOC(&signame), SILC_STR_UI32_NSTRING(&signature, &signature_len), SILC_STR_END) < 0) { verify_cb(FALSE, context); return NULL; } + memset(&sig, 0, sizeof(sig)); + + /* DSS signature must be formatted to PKIX compliant format since our + implementation expects that. */ + if (!strcmp(signame, "ssh-dss")) { + /* The integers must be 160 bits each */ + if (signature_len != 40) { + verify_cb(FALSE, context); + silc_free(signame); + return NULL; + } + + silc_buffer_set(&r, signature, 20); + silc_buffer_set(&s, signature + 20, 20); + + stack = silc_stack_alloc(0, silc_crypto_stack()); + + asn1 = silc_asn1_alloc(stack); + if (!asn1) { + verify_cb(FALSE, context); + silc_free(signame); + silc_stack_free(stack); + return NULL; + } + + /* Encode signature to PKIX compliant format. */ + if (!silc_asn1_encode(asn1, &sig, + SILC_ASN1_OPTS(SILC_ASN1_ALLOC), + SILC_ASN1_SEQUENCE, + SILC_ASN1_ANY_PRIMITIVE(SILC_ASN1_TAG_INTEGER, &r), + SILC_ASN1_ANY_PRIMITIVE(SILC_ASN1_TAG_INTEGER, &s), + SILC_ASN1_END, SILC_ASN1_END)) { + verify_cb(FALSE, context); + silc_free(signame); + silc_asn1_free(asn1); + silc_stack_free(stack); + return NULL; + } + + signature = silc_buffer_steal(&sig, &signature_len); + + silc_asn1_free(asn1); + } /* Verify */ - return pubkey->pkcs->verify(pubkey->pkcs, pubkey->public_key, - signature, signature_len, - data, data_len, hash, rng, - verify_cb, context); + op = pubkey->pkcs->verify(pubkey->pkcs, pubkey->public_key, + signature, signature_len, + data, data_len, hash, rng, + verify_cb, context); + + silc_free(signame); + silc_buffer_spurge(stack, &sig); + silc_stack_free(stack); + + return op; } /************************** SSH2 PKCS RSA Alg API ***************************/