Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions cryptokit/Sources/CryptoKitSrc/cryptokit.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import CommonCrypto
import CryptoKit
import Foundation

// Wrapper for SHA224 context since CommonCrypto's CC_SHA224_CTX may not be directly accessible
struct SHA224Hasher {
private var data = Data()

mutating func update(data: Data) {
self.data.append(data)
}

func finalize() -> Data {
var hash = [UInt8](repeating: 0, count: Int(CC_SHA224_DIGEST_LENGTH))
self.data.withUnsafeBytes {
_ = CC_SHA224($0.baseAddress, CC_LONG(self.data.count), &hash)
}
return Data(hash)
}
}

// Runtime feature detection for SHA3 (available on macOS 26+ only)
@_cdecl("go_supportsSHA3")
public func supportsSHA3() -> Int {
Expand Down Expand Up @@ -260,6 +278,17 @@ public func SHA1(
hashData.copyBytes(to: outputPointer, count: hashData.count)
}

@_cdecl("go_SHA224")
public func SHA224(
inputPointer: UnsafePointer<UInt8>,
inputLength: Int,
outputPointer: UnsafeMutablePointer<UInt8>
) -> Void {
var hash = [UInt8](repeating: 0, count: Int(CC_SHA224_DIGEST_LENGTH))
CC_SHA224(inputPointer, CC_LONG(inputLength), &hash)
Data(hash).copyBytes(to: outputPointer, count: hash.count)
}

@_cdecl("go_SHA256")
public func SHA256(
inputPointer: UnsafePointer<UInt8>,
Expand Down Expand Up @@ -352,6 +381,10 @@ public func hashNew(_ hashAlgorithm: Int32) -> UnsafeMutableRawPointer {
let hasher = UnsafeMutablePointer<Insecure.SHA1>.allocate(capacity: 1)
hasher.initialize(to: Insecure.SHA1())
return UnsafeMutableRawPointer(hasher)
case 9:
let hasher = UnsafeMutablePointer<SHA224Hasher>.allocate(capacity: 1)
hasher.initialize(to: SHA224Hasher())
return UnsafeMutableRawPointer(hasher)
case 3:
let hasher = UnsafeMutablePointer<CryptoKit.SHA256>.allocate(capacity: 1)
hasher.initialize(to: CryptoKit.SHA256())
Expand Down Expand Up @@ -421,6 +454,10 @@ public func hashWrite(
let hasher = ptr.assumingMemoryBound(to: Insecure.SHA1.self)
let buffer = UnsafeRawBufferPointer(start: data, count: length)
hasher.pointee.update(data: buffer)
case 9:
let hasher = ptr.assumingMemoryBound(to: SHA224Hasher.self)
let buffer = Data(bytes: data, count: length)
hasher.pointee.update(data: buffer)
case 3:
let hasher = ptr.assumingMemoryBound(to: CryptoKit.SHA256.self)
let buffer = UnsafeRawBufferPointer(start: data, count: length)
Expand Down Expand Up @@ -491,6 +528,10 @@ public func hashSum(

let hashData = hash.withUnsafeBytes { Data($0) }
hashData.copyBytes(to: outputPointer, count: hashData.count)
case 9:
let hasher = ptr.assumingMemoryBound(to: SHA224Hasher.self)
let hash = hasher.pointee.finalize()
hash.copyBytes(to: outputPointer, count: hash.count)
case 3:
let hasher = ptr.assumingMemoryBound(to: CryptoKit.SHA256.self)
let copiedHasher = hasher.pointee
Expand Down Expand Up @@ -571,6 +612,9 @@ public func hashReset(
case 2:
let hasher = ptr.assumingMemoryBound(to: Insecure.SHA1.self)
hasher.pointee = Insecure.SHA1()
case 9:
let hasher = ptr.assumingMemoryBound(to: SHA224Hasher.self)
hasher.pointee = SHA224Hasher()
case 3:
let hasher = ptr.assumingMemoryBound(to: CryptoKit.SHA256.self)
hasher.pointee = CryptoKit.SHA256()
Expand Down Expand Up @@ -622,6 +666,8 @@ public func hashSize(_ hashAlgorithm: Int32) -> Int {
return Insecure.MD5.byteCount
case 2:
return Insecure.SHA1.byteCount
case 9:
return Int(CC_SHA224_DIGEST_LENGTH)
case 3:
return CryptoKit.SHA256.byteCount
case 4:
Expand Down Expand Up @@ -667,6 +713,8 @@ public func hashBlockSize(_ hashAlgorithm: Int32) -> Int {
return Insecure.MD5.blockByteCount
case 2:
return Insecure.SHA1.blockByteCount
case 9:
return 64 // SHA224 block size is 64 bytes
case 3:
return CryptoKit.SHA256.blockByteCount
case 4:
Expand Down Expand Up @@ -721,6 +769,13 @@ public func hashCopy(_ hashAlgorithm: Int32, _ ptr: UnsafeMutableRawPointer) ->
let newHasher = UnsafeMutablePointer<Insecure.SHA1>.allocate(capacity: 1)
newHasher.initialize(to: copyOf)

return UnsafeMutableRawPointer(newHasher)
case 9:
let hasher = ptr.assumingMemoryBound(to: SHA224Hasher.self)
let copyOf = hasher.pointee
let newHasher = UnsafeMutablePointer<SHA224Hasher>.allocate(capacity: 1)
newHasher.initialize(to: copyOf)

return UnsafeMutableRawPointer(newHasher)
case 3:
let hasher = ptr.assumingMemoryBound(to: CryptoKit.SHA256.self)
Expand Down Expand Up @@ -811,6 +866,9 @@ public func hashFree(_ hashAlgorithm: Int32, _ ptr: UnsafeMutableRawPointer) {
case 2:
let hasher = ptr.assumingMemoryBound(to: Insecure.SHA1.self)
hasher.deallocate()
case 9:
let hasher = ptr.assumingMemoryBound(to: SHA224Hasher.self)
hasher.deallocate()
case 3:
let hasher = ptr.assumingMemoryBound(to: CryptoKit.SHA256.self)
hasher.deallocate()
Expand Down
45 changes: 45 additions & 0 deletions cryptokit/Tests/CryptoKitTests/hash.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import CommonCrypto
import CryptoKit
import Foundation
import XCTest
Expand Down Expand Up @@ -95,6 +96,35 @@ final class CryptoKitTests: XCTestCase {
XCTAssertEqual(Data(emptyOutput).hexEncodedString(), emptyExpectedHex)
}

// Test SHA224 hash function (Simple API)
func testSHA224_SimpleAPI() { // Renamed
let input = Array(simpleTestString.utf8)
var output = [UInt8](repeating: 0, count: 28) // SHA224 is 28 bytes

SHA224(
inputPointer: input,
inputLength: input.count,
outputPointer: &output
)

// Known SHA224 hash for the test string
let expectedHex = "730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525"
XCTAssertEqual(Data(output).hexEncodedString(), expectedHex)

// Test empty string
let emptyInput = Array(emptyString.utf8)
var emptyOutput = [UInt8](repeating: 0, count: 28)
SHA224(
inputPointer: emptyInput,
inputLength: emptyInput.count,
outputPointer: &emptyOutput
)

// Known SHA224 hash for empty string
let emptyExpectedHex = "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"
XCTAssertEqual(Data(emptyOutput).hexEncodedString(), emptyExpectedHex)
}

// Test SHA256 hash function (Simple API)
func testSHA256_SimpleAPI() { // Renamed
let input = Array(simpleTestString.utf8)
Expand Down Expand Up @@ -320,6 +350,21 @@ final class CryptoKitTests: XCTestCase {
knownEmptyHashHex: "da39a3ee5e6b4b0d3255bfef95601890afd80709",
knownTestStringHashHex: "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
),
HashingFunctions(
name: "SHA224",
new: { hashNew(9) },
write: { ptr, data, length in hashWrite(9, ptr, data, length) },
sum: { ptr, out in hashSum(9, ptr, out) },
reset: { ptr in hashReset(9, ptr) },
copy: { ptr in hashCopy(9, ptr) },
free: { ptr in hashFree(9, ptr) },
size: { hashSize(9) },
blockSize: { hashBlockSize(9) },
expectedSize: Int(CC_SHA224_DIGEST_LENGTH),
expectedBlockSize: 64,
knownEmptyHashHex: "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f",
knownTestStringHashHex: "2f05477fc24bb4faefd86517156dafdecec45b8ad3cf2522a563582b"
),
HashingFunctions(
name: "SHA256",
new: { hashNew(3) },
Expand Down
Binary file modified internal/cryptokit/CryptoKit_amd64.syso
Binary file not shown.
Binary file modified internal/cryptokit/CryptoKit_arm64.syso
Binary file not shown.
1 change: 1 addition & 0 deletions internal/cryptokit/shims.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ void *go_copyHMAC(int32_t hashAlgorithm, void *ptr) __attribute__((static));

void go_MD5(const uint8_t *inputPointer, size_t inputLength, const uint8_t *outputPointer) __attribute__((noescape, nocallback, static, slice(inputPointer, inputLength), slice(outputPointer)));
void go_SHA1(const uint8_t *inputPointer, size_t inputLength, const uint8_t *outputPointer) __attribute__((noescape, nocallback, static, slice(inputPointer, inputLength), slice(outputPointer)));
void go_SHA224(const uint8_t *inputPointer, size_t inputLength, const uint8_t *outputPointer) __attribute__((noescape, nocallback, static, slice(inputPointer, inputLength), slice(outputPointer)));
void go_SHA256(const uint8_t *inputPointer, size_t inputLength, const uint8_t *outputPointer) __attribute__((noescape, nocallback, static, slice(inputPointer, inputLength), slice(outputPointer)));
void go_SHA384(const uint8_t *inputPointer, size_t inputLength, const uint8_t *outputPointer) __attribute__((noescape, nocallback, static, slice(inputPointer, inputLength), slice(outputPointer)));
void go_SHA512(const uint8_t *inputPointer, size_t inputLength, const uint8_t *outputPointer) __attribute__((noescape, nocallback, static, slice(inputPointer, inputLength), slice(outputPointer)));
Expand Down
5 changes: 5 additions & 0 deletions internal/cryptokit/zcryptokit.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

void go_MD5(const uint8_t*, size_t, const uint8_t*);
void go_SHA1(const uint8_t*, size_t, const uint8_t*);
void go_SHA224(const uint8_t*, size_t, const uint8_t*);
void go_SHA256(const uint8_t*, size_t, const uint8_t*);
void go_SHA384(const uint8_t*, size_t, const uint8_t*);
void go_SHA3_256(const uint8_t*, size_t, const uint8_t*);
Expand Down Expand Up @@ -58,6 +59,10 @@ void _mkcgo_go_SHA1(const uint8_t* _arg0, size_t _arg1, const uint8_t* _arg2) {
go_SHA1(_arg0, _arg1, _arg2);
}

void _mkcgo_go_SHA224(const uint8_t* _arg0, size_t _arg1, const uint8_t* _arg2) {
go_SHA224(_arg0, _arg1, _arg2);
}

void _mkcgo_go_SHA256(const uint8_t* _arg0, size_t _arg1, const uint8_t* _arg2) {
go_SHA256(_arg0, _arg1, _arg2);
}
Expand Down
1 change: 1 addition & 0 deletions internal/cryptokit/zcryptokit.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ void mkcgo_err_free(mkcgo_err_state);

void _mkcgo_go_MD5(const uint8_t*, size_t, const uint8_t*);
void _mkcgo_go_SHA1(const uint8_t*, size_t, const uint8_t*);
void _mkcgo_go_SHA224(const uint8_t*, size_t, const uint8_t*);
void _mkcgo_go_SHA256(const uint8_t*, size_t, const uint8_t*);
void _mkcgo_go_SHA384(const uint8_t*, size_t, const uint8_t*);
void _mkcgo_go_SHA3_256(const uint8_t*, size_t, const uint8_t*);
Expand Down
5 changes: 5 additions & 0 deletions internal/cryptokit/zcryptokit.s
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ TEXT _mkcgo_go_SHA1_trampoline<>(SB),NOSPLIT,$0-0
GLOBL ·_mkcgo_go_SHA1_trampoline_addr(SB), RODATA, $_GOPTRSIZE
DATA ·_mkcgo_go_SHA1_trampoline_addr(SB)/_GOPTRSIZE, $_mkcgo_go_SHA1_trampoline<>(SB)

TEXT _mkcgo_go_SHA224_trampoline<>(SB),NOSPLIT,$0-0
JMP _mkcgo_go_SHA224(SB)
GLOBL ·_mkcgo_go_SHA224_trampoline_addr(SB), RODATA, $_GOPTRSIZE
DATA ·_mkcgo_go_SHA224_trampoline_addr(SB)/_GOPTRSIZE, $_mkcgo_go_SHA224_trampoline<>(SB)

TEXT _mkcgo_go_SHA256_trampoline<>(SB),NOSPLIT,$0-0
JMP _mkcgo_go_SHA256(SB)
GLOBL ·_mkcgo_go_SHA256_trampoline_addr(SB), RODATA, $_GOPTRSIZE
Expand Down
4 changes: 4 additions & 0 deletions internal/cryptokit/zcryptokit_cgo.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions internal/cryptokit/zcryptokit_cgo_go124.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions internal/cryptokit/zcryptokit_nocgo.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions internal/cryptokit/zcryptokit_swift_amd64.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading