Fixed SSH2 DSS signature decoding.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 22 Jul 2007 08:17:22 +0000 (08:17 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 22 Jul 2007 08:17:22 +0000 (08:17 +0000)
lib/silccrypt/DIRECTORY
lib/silcssh/silcssh.h
lib/silcssh/silcssh_pkcs.c

index 4a777cd5d8a517b192e98fd40bbb29e1522896c7..67556b69433f90b96012255a355e55abbca1e36b 100644 (file)
@@ -1,14 +1,14 @@
 <!--
 @LIBRARY=SILC Crypto Library
 @FILENAME=silccryptlib.html
-@LINK=silcrng_intro.html:Introduction to SILC RNG
-@LINK=silcrng.html:SILC RNG Interface
-@LINK=silccipher.html:SILC Cipher API
 @LINK=silcpkcs.html:SILC PKCS API
-@LINK=silcpk.html:SILC Public Key API
-@LINK=silcpkcs1.html:SILC PKCS #1 API
+@LINK=silccipher.html:SILC Cipher API
 @LINK=silchash.html:SILC Hash Interface
 @LINK=silchmac.html:SILC HMAC Interface
+@LINK=silcrng_intro.html:Introduction to SILC RNG
+@LINK=silcrng.html:SILC RNG Interface
+@LINK=silcpkcs1.html:SILC PKCS #1 API
+@LINK=silcpk.html:SILC Public Key API
 -->
 
 <big><b>SILC Crypto Library</b></big>
index acc989299bd7c6d34ab1da5cb6086c0e89f16f84..6c52bc7a8ea28e95748220fa389548256810657a 100644 (file)
  *
  * // 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.
index 4b370de6b720f90e14ee9e04b00a0175872e6bee..248aead791a38a6c4d4b25b39e51535f5139868e 100644 (file)
@@ -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 ***************************/