From c4222d2434eb877fc077cdb338ac22ab6779f412 Mon Sep 17 00:00:00 2001
From: godcansee <liu332084460@foxmail.com>
Date: Tue, 27 Sep 2022 19:55:55 +0800
Subject: [PATCH 1/4] nss add implement of SM3 digest algorithm

Signed-off-by: Huaxin Lu <luhuaxin1@huawei.com>
---
 lib/freebl/sm3.c | 274 +++++++++++++++++++++++++++++++++++++++++++++++
 lib/freebl/sm3.h |  19 ++++
 2 files changed, 293 insertions(+)
 create mode 100644 lib/freebl/sm3.c
 create mode 100644 lib/freebl/sm3.h

diff --git a/lib/freebl/sm3.c b/lib/freebl/sm3.c
new file mode 100644
index 0000000..27751ff
--- /dev/null
+++ b/lib/freebl/sm3.c
@@ -0,0 +1,274 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifdef FREEBL_NO_DEPEND
+#include "stubs.h"
+#endif
+
+#include "prerr.h"
+#include "prtypes.h"
+#include "prlong.h"
+#include "secport.h"
+#include "secerr.h"
+#include "blapi.h"
+#include "sm3.h"
+
+#define ROTATE(a,n)     (((a) << (n)) | (((a) & 0xffffffff) >> (32 - (n))))
+
+#define FF0(X,Y,Z) (X ^ Y ^ Z)
+#define GG0(X,Y,Z) (X ^ Y ^ Z)
+
+#define FF16(X,Y,Z) ((X & Y) | (X & Z) | (Y & Z))
+#define GG16(X,Y,Z) ((X & Y) | ((~X) & Z))
+
+#define P1(X) (X ^ ROTATE(X, 15) ^ ROTATE(X, 23))
+
+#define Get_32(l, c) ((l) = (PRUint32)(((*((PRUint8*)(c))) << 24) | \
+                                       ((*((PRUint8*)(c) + 1)) << 16) | \
+                                       ((*((PRUint8*)(c) + 2)) << 8) | \
+                                       ((*((PRUint8*)(c) + 3)))))
+
+#define Put_32(p, N) ((*((PRUint8*)(p))) = (PRUint8)((N) >> 24), \
+                      (*((PRUint8*)(p) + 1)) = (PRUint8)((N) >> 16), \
+                      (*((PRUint8*)(p) + 2)) = (PRUint8)((N) >> 8), \
+                      (*((PRUint8*)(p) + 3)) = (PRUint8)(N))
+
+void processOfSM3(SM3Context *ctx, const unsigned char *p) {
+    int j;
+    PRUint32 W[68];
+    PRUint32 A, B, C, D, E, F, G, H;
+    PRUint32 SS1, SS2, TT1, TT2;
+
+    A = ctx->A;
+    B = ctx->B;
+    C = ctx->C;
+    D = ctx->D;
+    E = ctx->E;
+    F = ctx->F;
+    G = ctx->G;
+    H = ctx->H;
+
+    for (j = 0; j < 16; j++)
+        Get_32(W[j], p + 4 * j);
+
+    for (j = 16; j <= 67; j++)
+        W[j] = P1(W[j - 16] ^ W[j - 9] ^ ROTATE(W[j - 3], 15)) ^ ROTATE(W[j - 13], 7) ^ W[j - 6];
+
+    for (j = 0; j < 16; j++) {
+        SS1 = ROTATE(A, 12);
+        SS1 = SS1 + E;
+        SS1 = SS1 + ROTATE(0x79cc4519UL, j);
+        SS1 = ROTATE(SS1, 7);
+        SS2 = SS1 ^ ROTATE(A, 12);
+        TT1 = FF0(A, B, C) + D;
+        TT1 = TT1 + SS2;
+        TT1 = TT1 + (W[j] ^ W[j + 4]);
+        TT2 = GG0(E, F, G) + H;
+        TT2 = TT2 + SS1;
+        TT2 = TT2 + W[j];
+        D = C;
+        C = ROTATE(B, 9);
+        B = A;
+        A = TT1;
+        H = G;
+        G = ROTATE(F, 19);
+        F = E;
+        E = TT2 ^ ROTATE(TT2, 9) ^ ROTATE(TT2, 17);
+    }
+
+    for (j = 16; j < 64; j++) {
+        SS1 = ROTATE(A, 12);
+        SS1 = SS1 + E;
+        SS1 = SS1 + ROTATE(0x7a879d8aUL, j & 0x1f);
+        SS1 = ROTATE(SS1, 7);
+        SS2 = SS1 ^ ROTATE(A, 12);
+        TT1 = FF16(A, B, C) + D;
+        TT1 = TT1 + SS2;
+        TT1 = TT1 + (W[j] ^ W[j + 4]);
+        TT2 = GG16(E, F, G) + H;
+        TT2 = TT2 + SS1;
+        TT2 = TT2 + W[j];
+        D = C;
+        C = ROTATE(B, 9);
+        B = A;
+        A = TT1;
+        H = G;
+        G = ROTATE(F, 19);
+        F = E;
+        E = TT2 ^ ROTATE(TT2, 9) ^ ROTATE(TT2, 17);
+    }
+
+    ctx->A ^= A;
+    ctx->B ^= B;
+    ctx->C ^= C;
+    ctx->D ^= D;
+    ctx->E ^= E;
+    ctx->F ^= F;
+    ctx->G ^= G;
+    ctx->H ^= H;
+}
+
+SM3Context *
+SM3_NewContext(void)
+{
+    SM3Context *ctx = PORT_New(SM3Context);
+    return ctx;
+}
+
+void
+SM3_DestroyContext(SM3Context *ctx, PRBool freeit)
+{
+    memset(ctx, 0, sizeof *ctx);
+    if (freeit) {
+        PORT_Free(ctx);
+    }
+}
+
+void
+SM3_Begin(SM3Context *ctx)
+{
+    memset(ctx, 0, sizeof(SM3Context));
+    ctx->A = 0x7380166fUL;
+    ctx->B = 0x4914b2b9UL;
+    ctx->C = 0x172442d7UL;
+    ctx->D = 0xda8a0600UL;
+    ctx->E = 0xa96f30bcUL;
+    ctx->F = 0x163138aaUL;
+    ctx->G = 0xe38dee4dUL;
+    ctx->H = 0xb0fb0e4eUL;
+}
+
+void
+SM3_Update(SM3Context *ctx, const unsigned char *input,
+           unsigned int inputLen)
+{
+    PRUint32 l, n, rest;
+    PRUint8 *p;
+
+    l = (ctx->Nl + (inputLen << 3)) & 0xffffffff;
+    if (l < ctx->Nl)
+        ctx->Nh++;
+
+    ctx->Nl = l;
+    ctx->Nh += (inputLen >> 29);
+    p = ctx->data;
+    n = ctx->num;
+
+    rest = 64 - n;
+    if (n) {
+        if (inputLen >= rest) {
+            memcpy(p + n, input, rest);
+            input += rest;
+            inputLen -= rest;
+            ctx->num = 0;
+            processOfSM3(ctx, p);
+            memset(p, 0, 64);
+        } else {
+            memcpy(p + n, input, inputLen);
+            ctx->num += inputLen;
+            return;
+        }
+    }
+
+    while (inputLen >= 64) {
+        processOfSM3(ctx, input);
+        input += 64;
+        inputLen -= 64;
+    }
+
+    if (inputLen) {
+        ctx->num = inputLen;
+        memcpy(ctx->data, input, inputLen);
+    }
+}
+
+void
+SM3_End(SM3Context *ctx, unsigned char *digest,
+        unsigned int *digestLen, unsigned int maxDigestLen)
+{
+    PRUint32 n = ctx->num;
+
+    if (maxDigestLen < SM3_LENGTH) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return;
+    }
+
+    ctx->data[n] = 0x80;
+
+    if (n >= 56) {
+        memset(ctx->data + n + 1, 0, 64 - n - 1);
+        processOfSM3(ctx, ctx->data);
+        memset(ctx->data, 0, 64);
+    }
+
+    Put_32(&ctx->data[56], ctx->Nh);
+    Put_32(&ctx->data[60], ctx->Nl);
+    processOfSM3(ctx, ctx->data);
+
+    Put_32(digest, ctx->A);
+    Put_32(digest + 4, ctx->B);
+    Put_32(digest + 8, ctx->C);
+    Put_32(digest + 12, ctx->D);
+    Put_32(digest + 16, ctx->E);
+    Put_32(digest + 20, ctx->F);
+    Put_32(digest + 24, ctx->G);
+    Put_32(digest + 28, ctx->H);
+
+    if (digestLen)
+        *digestLen = SM3_LENGTH;
+}
+
+SECStatus
+SM3_HashBuf(unsigned char *dest, const unsigned char *src,
+            PRUint32 src_length)
+{
+    SM3Context ctx;
+    unsigned int outLen;
+
+    SM3_Begin(&ctx);
+    SM3_Update(&ctx, src, src_length);
+    SM3_End(&ctx, dest, &outLen, SM3_LENGTH);
+    memset(&ctx, 0, sizeof ctx);
+
+    return SECSuccess;
+}
+
+SECStatus
+SM3_Hash(unsigned char *dest, const char *src)
+{
+    return SM3_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src));
+}
+
+void
+SM3_TraceState(SM3Context *ctx)
+{
+}
+
+unsigned int
+SM3_FlattenSize(SM3Context *ctx)
+{
+    return sizeof *ctx;
+}
+
+SECStatus
+SM3_Flatten(SM3Context *ctx, unsigned char *space)
+{
+    PORT_Memcpy(space, ctx, sizeof *ctx);
+    return SECSuccess;
+}
+
+SM3Context *
+SM3_Resurrect(unsigned char *space, void *arg)
+{
+    SM3Context *ctx = SM3_NewContext();
+    if (ctx)
+        PORT_Memcpy(ctx, space, sizeof *ctx);
+    return ctx;
+}
+
+void
+SM3_Clone(SM3Context *dest, SM3Context *src)
+{
+    memcpy(dest, src, sizeof *dest);
+}
diff --git a/lib/freebl/sm3.h b/lib/freebl/sm3.h
new file mode 100644
index 0000000..83d787f
--- /dev/null
+++ b/lib/freebl/sm3.h
@@ -0,0 +1,19 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _SM3_H_
+#define _SM3_H_
+
+#include "prtypes.h"
+
+struct SM3ContextStr {
+    PRUint32 A, B, C, D, E, F, G, H;
+    PRUint32 Nl, Nh;
+    PRUint8 data[64];
+    PRUint32 num;
+};
+
+
+
+#endif /* _SM3_H_ */
-- 
2.33.0