]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - sshsh512.c
first pass
[PuTTY.git] / sshsh512.c
index a2dd0c0b2316f29663b00b35d12ede3ec2bcb2d3..bdfc1e9dc71298630dfb444d49f83114136896c8 100644 (file)
@@ -2,6 +2,8 @@
  * SHA-512 algorithm as described at
  * 
  *   http://csrc.nist.gov/cryptval/shs.html
+ *
+ * Modifications made for SHA-384 also
  */
 
 #include "ssh.h"
  * overlap destination with one source, but the others can't.
  */
 #define add(r,x,y) ( r.lo = y.lo + x.lo, \
-                    r.hi = y.hi + x.hi + (r.lo < y.lo) )
-#define rorB(r,x,y) ( r.lo = (x.hi >> ((y)-32)) | (x.lo << (64-(y))), \
-                     r.hi = (x.lo >> ((y)-32)) | (x.hi << (64-(y))) )
-#define rorL(r,x,y) ( r.lo = (x.lo >> (y)) | (x.hi << (32-(y))), \
-                     r.hi = (x.hi >> (y)) | (x.lo << (32-(y))) )
-#define shrB(r,x,y) ( r.lo = x.hi >> ((y)-32), r.hi = 0 )
-#define shrL(r,x,y) ( r.lo = (x.lo >> (y)) | (x.hi << (32-(y))), \
-                     r.hi = x.hi >> (y) )
+                    r.hi = y.hi + x.hi + ((uint32)r.lo < (uint32)y.lo) )
+#define rorB(r,x,y) ( r.lo = ((uint32)x.hi >> ((y)-32)) | ((uint32)x.lo << (64-(y))), \
+                     r.hi = ((uint32)x.lo >> ((y)-32)) | ((uint32)x.hi << (64-(y))) )
+#define rorL(r,x,y) ( r.lo = ((uint32)x.lo >> (y)) | ((uint32)x.hi << (32-(y))), \
+                     r.hi = ((uint32)x.hi >> (y)) | ((uint32)x.lo << (32-(y))) )
+#define shrB(r,x,y) ( r.lo = (uint32)x.hi >> ((y)-32), r.hi = 0 )
+#define shrL(r,x,y) ( r.lo = ((uint32)x.lo >> (y)) | ((uint32)x.hi << (32-(y))), \
+                     r.hi = (uint32)x.hi >> (y) )
 #define and(r,x,y) ( r.lo = x.lo & y.lo, r.hi = x.hi & y.hi )
 #define xor(r,x,y) ( r.lo = x.lo ^ y.lo, r.hi = x.hi ^ y.hi )
 #define not(r,x) ( r.lo = ~x.lo, r.hi = ~x.hi )
@@ -45,7 +47,7 @@
 #define smallsigma1(r,t,x) ( rorL(r,x,19), rorB(t,x,61), xor(r,r,t), \
                             shrL(t,x,6), xor(r,r,t) )
 
-void SHA512_Core_Init(SHA512_State *s) {
+static void SHA512_Core_Init(SHA512_State *s) {
     static const uint64 iv[] = {
        INIT(0x6a09e667, 0xf3bcc908),
        INIT(0xbb67ae85, 0x84caa73b),
@@ -61,7 +63,23 @@ void SHA512_Core_Init(SHA512_State *s) {
        s->h[i] = iv[i];
 }
 
-void SHA512_Block(SHA512_State *s, uint64 *block) {
+static void SHA384_Core_Init(SHA512_State *s) {
+    static const uint64 iv[] = {
+        INIT(0xcbbb9d5d, 0xc1059ed8),
+        INIT(0x629a292a, 0x367cd507),
+        INIT(0x9159015a, 0x3070dd17),
+        INIT(0x152fecd8, 0xf70e5939),
+        INIT(0x67332667, 0xffc00b31),
+        INIT(0x8eb44a87, 0x68581511),
+        INIT(0xdb0c2e0d, 0x64f98fa7),
+        INIT(0x47b5481d, 0xbefa4fa4),
+    };
+    int i;
+    for (i = 0; i < 8; i++)
+        s->h[i] = iv[i];
+}
+
+static void SHA512_Block(SHA512_State *s, uint64 *block) {
     uint64 w[80];
     uint64 a,b,c,d,e,f,g,h;
     static const uint64 k[] = {
@@ -175,6 +193,14 @@ void SHA512_Init(SHA512_State *s) {
        s->len[i] = 0;
 }
 
+void SHA384_Init(SHA512_State *s) {
+    int i;
+    SHA384_Core_Init(s);
+    s->blkused = 0;
+    for (i = 0; i < 4; i++)
+        s->len[i] = 0;
+}
+
 void SHA512_Bytes(SHA512_State *s, const void *p, int len) {
     unsigned char *q = (unsigned char *)p;
     uint64 wordblock[16];
@@ -268,14 +294,104 @@ void SHA512_Final(SHA512_State *s, unsigned char *digest) {
     }
 }
 
+void SHA384_Final(SHA512_State *s, unsigned char *digest) {
+    unsigned char biggerDigest[512 / 8];
+    SHA512_Final(s, biggerDigest);
+    memcpy(digest, biggerDigest, 384 / 8);
+}
+
 void SHA512_Simple(const void *p, int len, unsigned char *output) {
     SHA512_State s;
 
     SHA512_Init(&s);
     SHA512_Bytes(&s, p, len);
     SHA512_Final(&s, output);
+    smemclr(&s, sizeof(s));
+}
+
+void SHA384_Simple(const void *p, int len, unsigned char *output) {
+    SHA512_State s;
+
+    SHA384_Init(&s);
+    SHA512_Bytes(&s, p, len);
+    SHA384_Final(&s, output);
+    smemclr(&s, sizeof(s));
+}
+
+/*
+ * Thin abstraction for things where hashes are pluggable.
+ */
+
+static void *sha512_init(void)
+{
+    SHA512_State *s;
+
+    s = snew(SHA512_State);
+    SHA512_Init(s);
+    return s;
+}
+
+static void *sha512_copy(const void *vold)
+{
+    const SHA512_State *old = (const SHA512_State *)vold;
+    SHA512_State *s;
+
+    s = snew(SHA512_State);
+    *s = *old;
+    return s;
+}
+
+static void sha512_free(void *handle)
+{
+    SHA512_State *s = handle;
+
+    smemclr(s, sizeof(*s));
+    sfree(s);
+}
+
+static void sha512_bytes(void *handle, const void *p, int len)
+{
+    SHA512_State *s = handle;
+
+    SHA512_Bytes(s, p, len);
 }
 
+static void sha512_final(void *handle, unsigned char *output)
+{
+    SHA512_State *s = handle;
+
+    SHA512_Final(s, output);
+    sha512_free(s);
+}
+
+const struct ssh_hash ssh_sha512 = {
+    sha512_init, sha512_copy, sha512_bytes, sha512_final, sha512_free,
+    64, "SHA-512"
+};
+
+static void *sha384_init(void)
+{
+    SHA512_State *s;
+
+    s = snew(SHA512_State);
+    SHA384_Init(s);
+    return s;
+}
+
+static void sha384_final(void *handle, unsigned char *output)
+{
+    SHA512_State *s = handle;
+
+    SHA384_Final(s, output);
+    smemclr(s, sizeof(*s));
+    sfree(s);
+}
+
+const struct ssh_hash ssh_sha384 = {
+    sha384_init, sha512_copy, sha512_bytes, sha384_final, sha512_free,
+    48, "SHA-384"
+};
+
 #ifdef TEST
 
 #include <stdio.h>