From 36767c7345161baf0ab125f95c8557f8e24f25db Mon Sep 17 00:00:00 2001
From: Randy Eckenrode <randy@largeandhighquality.com>
Date: Tue, 9 Apr 2024 19:28:17 -0400
Subject: [PATCH 7/8] Add OpenSSL-based CoreCrypto digest functions

---
 compat/CommonCrypto/CommonDigest.h    |  6 +++
 compat/CommonCrypto/CommonDigestSPI.c | 21 +++++++++++
 compat/CommonCrypto/CommonDigestSPI.h | 14 +++++++
 compat/corecrypto/api_defines.h       | 10 +++++
 compat/corecrypto/ccdigest.c          | 53 +++++++++++++++++++++++++++
 compat/corecrypto/ccdigest.h          | 27 ++++++++++++++
 compat/corecrypto/ccdigest_private.h  | 19 ++++++++++
 compat/corecrypto/ccsha1.c            | 22 +++++++++++
 compat/corecrypto/ccsha1.h            |  9 +++++
 compat/corecrypto/ccsha2.c            | 22 +++++++++++
 compat/corecrypto/ccsha2.h            |  9 +++++
 11 files changed, 212 insertions(+)
 create mode 100644 compat/CommonCrypto/CommonDigest.h
 create mode 100644 compat/CommonCrypto/CommonDigestSPI.c
 create mode 100644 compat/CommonCrypto/CommonDigestSPI.h
 create mode 100644 compat/corecrypto/api_defines.h
 create mode 100644 compat/corecrypto/ccdigest.c
 create mode 100644 compat/corecrypto/ccdigest.h
 create mode 100644 compat/corecrypto/ccdigest_private.h
 create mode 100644 compat/corecrypto/ccsha1.c
 create mode 100644 compat/corecrypto/ccsha1.h
 create mode 100644 compat/corecrypto/ccsha2.c
 create mode 100644 compat/corecrypto/ccsha2.h

diff --git a/compat/CommonCrypto/CommonDigest.h b/compat/CommonCrypto/CommonDigest.h
new file mode 100644
index 0000000..a60eba7
--- /dev/null
+++ b/compat/CommonCrypto/CommonDigest.h
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: APSL-2.0
+// CoreCrypto compatibility shims written by Randy Eckenrode © 2024
+
+#pragma once
+
+#define CCSHA256_OUTPUT_SIZE 32
diff --git a/compat/CommonCrypto/CommonDigestSPI.c b/compat/CommonCrypto/CommonDigestSPI.c
new file mode 100644
index 0000000..41269fc
--- /dev/null
+++ b/compat/CommonCrypto/CommonDigestSPI.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: APSL-2.0
+// CoreCrypto compatibility shims written by Randy Eckenrode © 2024
+
+#include "CommonDigestSPI.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <corecrypto/ccsha2.h>
+
+void CCDigest(int type, const uint8_t* bytes, size_t count, uint8_t* digest) {
+    if (type != kCCDigestSHA256) {
+        abort();
+    }
+    const struct ccdigest_info* di = ccsha256_di();
+
+    ccdigest_di_decl(_di, ctx);
+    ccdigest_init(di, ctx);
+    ccdigest_update(di, ctx, count, bytes);
+    ccdigest_final(di, ctx, digest);
+}
diff --git a/compat/CommonCrypto/CommonDigestSPI.h b/compat/CommonCrypto/CommonDigestSPI.h
new file mode 100644
index 0000000..172742a
--- /dev/null
+++ b/compat/CommonCrypto/CommonDigestSPI.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: APSL-2.0
+// CoreCrypto compatibility shims written by Randy Eckenrode © 2024
+
+#pragma once
+
+#include <stdint.h>
+
+#include <corecrypto/ccdigest.h>
+#include <cs_blobs.h>
+
+
+#define kCCDigestSHA256 10
+
+EXTERN_C void CCDigest(int type, const uint8_t* bytes, size_t count, uint8_t* digest);
diff --git a/compat/corecrypto/api_defines.h b/compat/corecrypto/api_defines.h
new file mode 100644
index 0000000..13d1e7a
--- /dev/null
+++ b/compat/corecrypto/api_defines.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: APSL-2.0
+// CoreCrypto compatibility shims written by Randy Eckenrode © 2024
+
+#pragma once
+
+#ifdef __cplusplus
+#define EXTERN_C extern "C"
+#else
+#define EXTERN_C
+#endif
diff --git a/compat/corecrypto/ccdigest.c b/compat/corecrypto/ccdigest.c
new file mode 100644
index 0000000..e29dcb8
--- /dev/null
+++ b/compat/corecrypto/ccdigest.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: APSL-2.0
+// CoreCrypto compatibility shims written by Randy Eckenrode © 2024
+
+#include "ccdigest.h"
+#include "ccdigest_private.h"
+
+#include <stdlib.h>
+
+#include <openssl/err.h>
+
+
+struct ccdigest_context* _ccdigest_context_new(void)
+{
+    struct ccdigest_context* ctx = malloc(sizeof(struct ccdigest_context));
+    ctx->context = EVP_MD_CTX_new();
+    return ctx;
+}
+
+struct ccdigest_info* _ccdigest_newprovider(const char* name)
+{
+    struct ccdigest_info* di = malloc(sizeof(struct ccdigest_info));
+    di->provider = EVP_MD_fetch(NULL, name, NULL);
+    return di;
+}
+
+void ccdigest_init(const struct ccdigest_info* di, struct ccdigest_context* ctx)
+{
+    if (!EVP_DigestInit_ex2(ctx->context, di->provider, NULL)) {
+        ERR_print_errors_fp(stderr);
+        abort();
+    }
+}
+
+void ccdigest_update(
+    const struct ccdigest_info* _di,
+    struct ccdigest_context* ctx,
+    size_t count,
+    const void* bytes
+)
+{
+    if (!EVP_DigestUpdate(ctx->context, bytes, count)) {
+        ERR_print_errors_fp(stderr);
+        abort();
+    }
+}
+
+void ccdigest_final(const struct ccdigest_info* _di, struct ccdigest_context* ctx, uint8_t* digest)
+{
+    if (!EVP_DigestFinal_ex(ctx->context, digest, NULL)) {
+        ERR_print_errors_fp(stderr);
+        abort();
+    }
+}
diff --git a/compat/corecrypto/ccdigest.h b/compat/corecrypto/ccdigest.h
new file mode 100644
index 0000000..9af2394
--- /dev/null
+++ b/compat/corecrypto/ccdigest.h
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: APSL-2.0
+// CoreCrypto compatibility shims written by Randy Eckenrode © 2024
+
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "api_defines.h"
+
+
+struct ccdigest_info;
+struct ccdigest_context;
+
+EXTERN_C struct ccdigest_context* _ccdigest_context_new(void);
+
+#define ccdigest_di_decl(_di, ctxvar) \
+    struct ccdigest_context* (ctxvar) = _ccdigest_context_new()
+
+EXTERN_C void ccdigest_init(const struct ccdigest_info* di, struct ccdigest_context* ctx);
+EXTERN_C void ccdigest_update(
+    const struct ccdigest_info* _di,
+    struct ccdigest_context* ctx,
+    size_t count,
+    const void* bytes
+);
+EXTERN_C void ccdigest_final(const struct ccdigest_info* _di, struct ccdigest_context* ctx, uint8_t* digest);
diff --git a/compat/corecrypto/ccdigest_private.h b/compat/corecrypto/ccdigest_private.h
new file mode 100644
index 0000000..0ea9759
--- /dev/null
+++ b/compat/corecrypto/ccdigest_private.h
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: APSL-2.0
+// CoreCrypto compatibility shims written by Randy Eckenrode © 2024
+
+#pragma once
+
+#include "api_defines.h"
+
+#include <openssl/evp.h>
+
+
+struct ccdigest_info {
+    EVP_MD* provider;
+};
+
+struct ccdigest_context {
+    EVP_MD_CTX* context;
+};
+
+EXTERN_C struct ccdigest_info* _ccdigest_newprovider(const char* name);
diff --git a/compat/corecrypto/ccsha1.c b/compat/corecrypto/ccsha1.c
new file mode 100644
index 0000000..e02b2b6
--- /dev/null
+++ b/compat/corecrypto/ccsha1.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: APSL-2.0
+// CoreCrypto compatibility shims written by Randy Eckenrode © 2024
+
+#include "ccsha1.h"
+
+#include <assert.h>
+
+#include <cs_blobs.h>
+
+#include "ccdigest_private.h"
+
+
+static struct ccdigest_info* di = NULL;
+
+const struct ccdigest_info* ccsha1_di(void)
+{
+    if (!di) {
+        di = _ccdigest_newprovider("SHA-1");
+        assert(EVP_MD_get_size(di->provider) == CS_SHA1_LEN);
+    }
+    return di;
+}
diff --git a/compat/corecrypto/ccsha1.h b/compat/corecrypto/ccsha1.h
new file mode 100644
index 0000000..8e3f85f
--- /dev/null
+++ b/compat/corecrypto/ccsha1.h
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: APSL-2.0
+// CoreCrypto compatibility shims written by Randy Eckenrode © 2024
+
+#pragma once
+
+#include <corecrypto/ccdigest.h>
+
+
+EXTERN_C const struct ccdigest_info* ccsha1_di(void);
diff --git a/compat/corecrypto/ccsha2.c b/compat/corecrypto/ccsha2.c
new file mode 100644
index 0000000..6504503
--- /dev/null
+++ b/compat/corecrypto/ccsha2.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: APSL-2.0
+// CoreCrypto compatibility shims written by Randy Eckenrode © 2024
+
+#include "ccsha2.h"
+
+#include <assert.h>
+
+#include <cs_blobs.h>
+
+#include "ccdigest_private.h"
+
+
+static struct ccdigest_info* di = NULL;
+
+const struct ccdigest_info* ccsha256_di(void)
+{
+    if (!di) {
+        di = _ccdigest_newprovider("SHA-256");
+        assert(EVP_MD_get_size(di->provider) == CS_SHA256_LEN);
+    }
+    return di;
+}
diff --git a/compat/corecrypto/ccsha2.h b/compat/corecrypto/ccsha2.h
new file mode 100644
index 0000000..9f30e03
--- /dev/null
+++ b/compat/corecrypto/ccsha2.h
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: APSL-2.0
+// CoreCrypto compatibility shims written by Randy Eckenrode © 2024
+
+#pragma once
+
+#include <corecrypto/ccdigest.h>
+
+
+EXTERN_C const struct ccdigest_info* ccsha256_di(void);
-- 
2.45.1