1919protocol HashFunctionImplementationDetails : HashFunction where Digest: DigestPrivate { }
2020
2121protocol BoringSSLBackedHashFunction : HashFunctionImplementationDetails {
22- static var digestType : DigestContext . DigestType { get }
22+ associatedtype Context
23+ static var digestSize : Int { get }
24+ static func initialize( ) -> Context ?
25+ static func update( _ context: inout Context , data: UnsafeRawBufferPointer ) -> Bool
26+ static func finalize( _ context: inout Context , digest: UnsafeMutableRawBufferPointer ) -> Bool
2327}
2428
2529extension Insecure . MD5 : BoringSSLBackedHashFunction {
26- static var digestType : DigestContext . DigestType {
27- . md5
30+ static var digestSize : Int {
31+ Int ( MD5_DIGEST_LENGTH)
32+ }
33+
34+ static func initialize( ) -> MD5_CTX ? {
35+ var context = MD5_CTX ( )
36+ guard CCryptoBoringSSL_MD5_Init ( & context) == 1 else {
37+ return nil
38+ }
39+ return context
40+ }
41+
42+ static func update( _ context: inout MD5_CTX , data: UnsafeRawBufferPointer ) -> Bool {
43+ CCryptoBoringSSL_MD5_Update ( & context, data. baseAddress, data. count) == 1
44+ }
45+
46+ static func finalize( _ context: inout MD5_CTX , digest: UnsafeMutableRawBufferPointer ) -> Bool {
47+ CCryptoBoringSSL_MD5_Final ( digest. baseAddress, & context) == 1
2848 }
2949}
3050
3151extension Insecure . SHA1 : BoringSSLBackedHashFunction {
32- static var digestType : DigestContext . DigestType {
33- . sha1
52+ static var digestSize : Int {
53+ Int ( SHA_DIGEST_LENGTH)
54+ }
55+
56+ static func initialize( ) -> SHA_CTX ? {
57+ var context = SHA_CTX ( )
58+ guard CCryptoBoringSSL_SHA1_Init ( & context) == 1 else {
59+ return nil
60+ }
61+ return context
62+ }
63+
64+ static func update( _ context: inout SHA_CTX , data: UnsafeRawBufferPointer ) -> Bool {
65+ CCryptoBoringSSL_SHA1_Update ( & context, data. baseAddress, data. count) == 1
66+ }
67+
68+ static func finalize( _ context: inout SHA_CTX , digest: UnsafeMutableRawBufferPointer ) -> Bool {
69+ CCryptoBoringSSL_SHA1_Final ( digest. baseAddress, & context) == 1
3470 }
3571}
3672
3773extension SHA256 : BoringSSLBackedHashFunction {
38- static var digestType : DigestContext . DigestType {
39- . sha256
74+ static var digestSize : Int {
75+ Int ( SHA256_DIGEST_LENGTH)
76+ }
77+
78+ static func initialize( ) -> SHA256_CTX ? {
79+ var context = SHA256_CTX ( )
80+ guard CCryptoBoringSSL_SHA256_Init ( & context) == 1 else {
81+ return nil
82+ }
83+ return context
84+ }
85+
86+ static func update( _ context: inout SHA256_CTX , data: UnsafeRawBufferPointer ) -> Bool {
87+ CCryptoBoringSSL_SHA256_Update ( & context, data. baseAddress, data. count) == 1
88+ }
89+
90+ static func finalize( _ context: inout SHA256_CTX , digest: UnsafeMutableRawBufferPointer ) -> Bool {
91+ CCryptoBoringSSL_SHA256_Final ( digest. baseAddress, & context) == 1
4092 }
4193}
4294
4395extension SHA384 : BoringSSLBackedHashFunction {
44- static var digestType : DigestContext . DigestType {
45- . sha384
96+ static var digestSize : Int {
97+ Int ( SHA384_DIGEST_LENGTH)
98+ }
99+
100+ static func initialize( ) -> SHA512_CTX ? {
101+ var context = SHA512_CTX ( )
102+ guard CCryptoBoringSSL_SHA384_Init ( & context) == 1 else {
103+ return nil
104+ }
105+ return context
106+ }
107+
108+ static func update( _ context: inout SHA512_CTX , data: UnsafeRawBufferPointer ) -> Bool {
109+ CCryptoBoringSSL_SHA384_Update ( & context, data. baseAddress, data. count) == 1
110+ }
111+
112+ static func finalize( _ context: inout SHA512_CTX , digest: UnsafeMutableRawBufferPointer ) -> Bool {
113+ CCryptoBoringSSL_SHA384_Final ( digest. baseAddress, & context) == 1
46114 }
47115}
48116
49117extension SHA512 : BoringSSLBackedHashFunction {
50- static var digestType : DigestContext . DigestType {
51- . sha512
118+ static var digestSize : Int {
119+ Int ( SHA512_DIGEST_LENGTH)
120+ }
121+
122+ static func initialize( ) -> SHA512_CTX ? {
123+ var context = SHA512_CTX ( )
124+ guard CCryptoBoringSSL_SHA512_Init ( & context) == 1 else {
125+ return nil
126+ }
127+ return context
128+ }
129+
130+ static func update( _ context: inout SHA512_CTX , data: UnsafeRawBufferPointer ) -> Bool {
131+ CCryptoBoringSSL_SHA512_Update ( & context, data. baseAddress, data. count) == 1
132+ }
133+
134+ static func finalize( _ context: inout SHA512_CTX , digest: UnsafeMutableRawBufferPointer ) -> Bool {
135+ CCryptoBoringSSL_SHA512_Final ( digest. baseAddress, & context) == 1
52136 }
53137}
54138
55139struct OpenSSLDigestImpl < H: BoringSSLBackedHashFunction > {
56- private var context : DigestContext
140+ private var context : DigestContext < H >
57141
58142 init ( ) {
59- self . context = DigestContext ( digest : H . digestType )
143+ self . context = DigestContext ( )
60144 }
61145
62146 internal mutating func update( data: UnsafeRawBufferPointer ) {
@@ -67,81 +151,49 @@ struct OpenSSLDigestImpl<H: BoringSSLBackedHashFunction> {
67151 }
68152
69153 internal func finalize( ) -> H . Digest {
70- // To have a non-destructive finalize operation we must allocate.
71- let copyContext = DigestContext ( copying: self . context)
72- let digestBytes = copyContext. finalize ( )
73- return digestBytes. withUnsafeBytes {
74- // We force unwrap here because if the digest size is wrong it's an internal error.
75- H . Digest ( bufferPointer: $0) !
76- }
154+ self . context. finalize ( )
77155 }
78156}
79157
80- class DigestContext {
81- private var contextPointer : UnsafeMutablePointer < EVP_MD_CTX >
158+ fileprivate final class DigestContext < H : BoringSSLBackedHashFunction > {
159+ private var context : H . Context
82160
83- init ( digest: DigestType ) {
84- // We force unwrap because we cannot recover from allocation failure.
85- self . contextPointer = CCryptoBoringSSL_EVP_MD_CTX_new ( ) !
86- guard CCryptoBoringSSL_EVP_DigestInit ( self . contextPointer, digest. dispatchTable) != 0 else {
87- // We can't do much but crash here.
88- fatalError ( " Unable to initialize digest state: \( CCryptoBoringSSL_ERR_get_error ( ) ) " )
161+ init ( ) {
162+ guard let contex = H . initialize ( ) else {
163+ preconditionFailure ( " Unable to initialize digest state " )
89164 }
165+ self . context = contex
90166 }
91167
92168 init ( copying original: DigestContext ) {
93- // We force unwrap because we cannot recover from allocation failure.
94- self . contextPointer = CCryptoBoringSSL_EVP_MD_CTX_new ( ) !
95- guard CCryptoBoringSSL_EVP_MD_CTX_copy ( self . contextPointer, original. contextPointer) != 0 else {
96- // We can't do much but crash here.
97- fatalError ( " Unable to copy digest state: \( CCryptoBoringSSL_ERR_get_error ( ) ) " )
98- }
169+ self . context = original. context
99170 }
100171
101172 func update( data: UnsafeRawBufferPointer ) {
102- guard let baseAddress = data. baseAddress else {
103- return
173+ guard H . update ( & self . context , data : data) else {
174+ preconditionFailure ( " Unable to update digest state " )
104175 }
105-
106- CCryptoBoringSSL_EVP_DigestUpdate ( self . contextPointer, baseAddress, data. count)
107176 }
108177
109- // This finalize function is _destructive_: do not call it if you want to reuse the object!
110- func finalize( ) -> [ UInt8 ] {
111- let digestSize = CCryptoBoringSSL_EVP_MD_size ( self . contextPointer. pointee. digest)
112- var digestBytes = Array ( repeating: UInt8 ( 0 ) , count: digestSize)
113- var count = UInt32 ( digestSize)
114-
115- digestBytes. withUnsafeMutableBufferPointer { digestPointer in
116- assert ( digestPointer. count == count)
117- CCryptoBoringSSL_EVP_DigestFinal ( self . contextPointer, digestPointer. baseAddress, & count)
178+ func finalize( ) -> H . Digest {
179+ var copyContext = self . context
180+ defer {
181+ withUnsafeMutablePointer ( to: & copyContext) { $0. zeroize ( ) }
182+ }
183+ return withUnsafeTemporaryAllocation ( byteCount: H . digestSize, alignment: 1 ) { digestPointer in
184+ defer {
185+ digestPointer. zeroize ( )
186+ }
187+ guard H . finalize ( & copyContext, digest: digestPointer) else {
188+ preconditionFailure ( " Unable to finalize digest state " )
189+ }
190+ // We force unwrap here because if the digest size is wrong it's an internal error.
191+ return H . Digest ( bufferPointer: UnsafeRawBufferPointer ( digestPointer) ) !
118192 }
119-
120- return digestBytes
121193 }
122194
123195 deinit {
124- CCryptoBoringSSL_EVP_MD_CTX_free ( self . contextPointer)
125- }
126- }
127-
128- extension DigestContext {
129- struct DigestType {
130- var dispatchTable : OpaquePointer
131-
132- private init ( _ dispatchTable: OpaquePointer ) {
133- self . dispatchTable = dispatchTable
134- }
135-
136- static let md5 = DigestType ( CCryptoBoringSSL_EVP_md5 ( ) )
137-
138- static let sha1 = DigestType ( CCryptoBoringSSL_EVP_sha1 ( ) )
139-
140- static let sha256 = DigestType ( CCryptoBoringSSL_EVP_sha256 ( ) )
141-
142- static let sha384 = DigestType ( CCryptoBoringSSL_EVP_sha384 ( ) )
143-
144- static let sha512 = DigestType ( CCryptoBoringSSL_EVP_sha512 ( ) )
196+ withUnsafeMutablePointer ( to: & self . context) { $0. zeroize ( ) }
145197 }
146198}
147199#endif // CRYPTO_IN_SWIFTPM && !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
0 commit comments