Skip to content

Commit

Permalink
Version 3.0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Gematik-Entwicklung committed May 5, 2022
1 parent 3927c1a commit e1ef859
Show file tree
Hide file tree
Showing 18 changed files with 470 additions and 78 deletions.
15 changes: 12 additions & 3 deletions Config/ios-conf.patch
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
1574a1575,1589
1671a1672,1695
> "ios64sim-cross" => {
> inherit_from => [ "darwin-common", asm("no_asm") ],
> inherit_from => [ "ios-common" ],
> cflags => add("-arch x86_64 -DOPENSSL_NO_ASM -mios-version-min=7.0.0 -isysroot \$(CROSS_TOP)/SDKs/\$(CROSS_SDK) -fno-common"),
> module_ldflags => "-shared",
> LDFLAGS => "-shared",
> sys_id => "iOS",
> bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR",
> perlasm_scheme => "ios64",
> },
> "ios64sim-arm64-cross" => {
> inherit_from => [ "darwin-common", asm("no_asm") ],
> inherit_from => [ "darwin-common" ],
> CC => "xcrun -sdk iphonesimulator cc",
> cflags => add("-arch arm64 -DOPENSSL_NO_ASM -mios-simulator-version-min=14.0.0 -isysroot \$(CROSS_TOP)/SDKs/\$(CROSS_SDK) -fno-common"),
> sys_id => "iOS",
> module_ldflags => "-shared",
> LDFLAGS => "-shared",
> bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR",
> perlasm_scheme => "ios64",
> },
> "ios64-cross-fix" => {
> inherit_from => [ "ios64-cross" ],
> module_ldflags => "-shared",
> LDFLAGS => "-shared",
> },
7 changes: 7 additions & 0 deletions Config/shared-info.pl.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
--- Configurations/shared-info.pl 2022-03-25 13:37:12.000000000 +0100
+++ Configurations/shared-info.pl 2022-03-25 13:37:18.000000000 +0100
@@ -44,2 +44,2 @@
- module_ldflags => '-bundle',
- shared_ldflag => '-dynamiclib -current_version $(SHLIB_VERSION_NUMBER) -compatibility_version $(SHLIB_VERSION_NUMBER)',
+ module_ldflags => '',
+ shared_ldflag => '-current_version $(SHLIB_VERSION_NUMBER) -compatibility_version $(SHLIB_VERSION_NUMBER)',
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -296,4 +296,4 @@ RUBY VERSION
ruby 2.6.5p114

BUNDLED WITH
2.2.16
2.3.11
75 changes: 53 additions & 22 deletions OpenSSL-Swift.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "1200"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
buildImplicitDependencies = "YES"
runPostActionsOnFailure = "NO">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
Expand Down Expand Up @@ -52,10 +53,6 @@
</MacroExpansion>
<CommandLineArguments>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
<CodeCoverageTargets>
</CodeCoverageTargets>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand All @@ -78,8 +75,6 @@
</MacroExpansion>
<CommandLineArguments>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "1200"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
buildImplicitDependencies = "YES"
runPostActionsOnFailure = "NO">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
Expand Down Expand Up @@ -52,10 +53,6 @@
</MacroExpansion>
<CommandLineArguments>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
<CodeCoverageTargets>
</CodeCoverageTargets>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand All @@ -78,8 +75,6 @@
</MacroExpansion>
<CommandLineArguments>
</CommandLineArguments>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Swift extension wrapper for gematik specific crypto operations with embedded Ope

## Overview

This Xcode-project downloads, compiles and embeds OpenSSL version 1.1.1n in a Swift framework that can be included
This Xcode-project downloads, compiles and embeds OpenSSL version 3.0.2 in a Swift framework that can be included
in MacOS/iOS Frameworks and Apps.

There are three main parts of this project.
Expand Down Expand Up @@ -40,7 +40,7 @@ the binary libraries that are built by this project. [We don't support CocoaPods

```Cartfile
git "https://github.com/gematik/openssl-swift.git" ~> 1.0
git "https://github.com/gematik/openssl-swift.git" ~> 3.0
```

```shell script
Expand Down Expand Up @@ -103,6 +103,21 @@ let options: OCSPResponse.BasicVerifyOptions = [.noChecks]
try vauOcspResponse.basicVerifyWith(trustedStore: [ocspSignerCa, rootCa], options: options)
```

### Cryptographic Message Syntax

CMS-Encryption of a message for (multiple) `X509` recipient certificate(s) (for now only RSA!) is supported. An *Authenticated-Enveloped-Data Content Type* structure using *AES 256 GCM* will be created.

```swift
let x509rsa = try X509(pem: x509rsaPem.data(using: .utf8)!)
let x509ecc = try X509(pem: x509eccPem.data(using: .utf8)!)
let recipients = [x509rsa, x509ecc]
let data = message.data(using: .utf8)!
let cms = try CMSContentInfo.encryptPartial(data: data)
try cms.addRecipientsRSAOnly(recipients)
try cms.final(data: data)
print(cms.derBytes?.hexString())
```

### Key Management

Cryptographic operations are often based on public / private keys that here are represented by the
Expand Down
8 changes: 8 additions & 0 deletions ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Release 3.0.2

# OpenSSL 3.0.2

- Upgrade to OpenSSL 3.0.2
- Fix some of the introduced deprecations
- Add support for CMSContentInfo Encryption

# Release 1.0.1

- SDK 15
Expand Down
119 changes: 119 additions & 0 deletions Sources/OpenSSL/CMS/CMSContentInfo.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//
// Copyright (c) 2022 gematik GmbH
//
// Licensed under the EUPL, Version 1.2 or – as soon they will be approved by
// the European Commission - subsequent versions of the EUPL (the Licence);
// You may not use this work except in compliance with the Licence.
// You may obtain a copy of the Licence at:
//
// https://joinup.ec.europa.eu/software/page/eupl
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Licence is distributed on an "AS IS" basis,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the Licence for the specific language governing permissions and
// limitations under the Licence.
//
//

@_implementationOnly import COpenSSL
import Foundation

/// CMSContentInfo
public class CMSContentInfo {
let cms: OpaquePointer

init() {
cms = CMS_ContentInfo_new()
}

required init(owningNoCopy cms: OpaquePointer) {
self.cms = cms
}

/// De-initialize
deinit {
CMS_ContentInfo_free(cms)
}

/// Get the DER byte representation as `Data`
public var derBytes: Data? {
var dataPtr: UnsafeMutablePointer<UInt8>?
let length = i2d_CMS_ContentInfo(cms, &dataPtr)
guard length > 0, let safeDataPtr = dataPtr else {
return nil
}

return Data(bytesNoCopy: safeDataPtr, count: Int(length), deallocator: .free)
}

/// Entry step for the `encryptPartial`, `addRecipients`, `final` (as in `init`, `update`, `final`) cycle.
///
/// - Important: Encryption is done by `aes_256_gcm`
/// - Parameter data: Data (e.g. a message) to be encrypted
/// - Returns: A (partially) initialized `CMSContentInfo`
/// - Throws: `OpenSSLError`
public static func encryptPartial(data: Data) throws -> Self {
let flagPartial = UInt32(CMS_PARTIAL) // don't call `finalize` immediately
let flags = flagPartial

let cms: OpaquePointer!
cms = try data.withUnsafeBytes { unsafeRawBufferPointer in
let bytesPtr = unsafeRawBufferPointer.bindMemory(to: UInt8.self).baseAddress
let dataBio = BIO_new_mem_buf(bytesPtr, Int32(unsafeRawBufferPointer.count))
defer { BIO_free(dataBio) }

guard let ret = CMS_encrypt(nil, dataBio, EVP_aes_256_gcm(), flags) else {
throw OpenSSLError(name: "Error calling CMS_encrypt()")
}
return ret
}
return .init(owningNoCopy: cms)
}

/// Update step for the `encryptPartial`, `addRecipients`, `final` (as in `init`, `update`, `final`) cycle.
///
/// - Important: This will only work with `X509` certificates that contain a RSA public key!
/// - Parameter recipients:
/// - Throws: `OpenSSLError`
public func addRecipientsRSAOnly(_ recipients: [X509]) throws {
let flagPartial = UInt32(CMS_PARTIAL) // don't call `finalize` immediately
let flags = flagPartial

for recipient in recipients {
var ri: OpaquePointer! // swiftlint:disable:this identifier_name
var pctx: OpaquePointer!
ri = CMS_add1_recipient_cert(cms, recipient.x509, flags | UInt32(CMS_KEY_PARAM))
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri)
guard EVP_PKEY_CTX_set_rsa_oaep_md(pctx, EVP_sha256()) == 1 else {
throw OpenSSLError(name: "Error calling EVP_PKEY_CTX_set_rsa_oaep_md()")
}
guard EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, EVP_sha256()) == 1 else {
throw OpenSSLError(name: "Error calling EVP_PKEY_CTX_set_rsa_mgf1_md()")
}
guard EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_OAEP_PADDING) == 1 else {
throw OpenSSLError(name: "Error calling EVP_PKEY_CTX_set_rsa_padding()")
}
}
}

/// Final step for the `encryptPartial`, `addRecipients`, `final` (as in `init`, `update`, `final`) cycle.
///
/// - Parameter data: Data (e.g. a message) to be encrypted
/// - Throws: `OpenSSLError`
public func final(data: Data) throws {
let flagPartial = UInt32(CMS_PARTIAL) // don't call `finalize` immediately
let flags = flagPartial

try data.withUnsafeBytes { unsafeRawBufferPointer in
let bytesPtr = unsafeRawBufferPointer.bindMemory(to: UInt8.self).baseAddress
let dataBio = BIO_new_mem_buf(bytesPtr, Int32(unsafeRawBufferPointer.count))
defer {
BIO_free(dataBio)
}
guard CMS_final(cms, dataBio, nil, flags) == 1 else {
throw OpenSSLError(name: "Error calling CMS_final()")
}
}
}
}
1 change: 1 addition & 0 deletions Sources/OpenSSL/COpenSSL/shim.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef COpenSSL_H
#define COpenSSL_H

#include <openssl/cms.h>
#include <openssl/conf.h>
#include <openssl/bn.h>
#include <openssl/cmac.h>
Expand Down
4 changes: 2 additions & 2 deletions Sources/OpenSSL/Certificate/X509.swift
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ extension X509 {
EVP_PKEY_free(publicKey)
}

guard NID_X9_62_id_ecPublicKey == EVP_PKEY_id(publicKey),
guard NID_X9_62_id_ecPublicKey == EVP_PKEY_get_id(publicKey),
let ecKey = EVP_PKEY_get0_EC_KEY(publicKey),
NID_brainpoolP256r1 == EC_GROUP_get_curve_name(EC_KEY_get0_group(ecKey)),
let duplicate = EC_KEY_dup(ecKey) else {
Expand All @@ -356,7 +356,7 @@ extension X509 {
EVP_PKEY_free(publicKey)
}

guard NID_X9_62_id_ecPublicKey == EVP_PKEY_id(publicKey),
guard NID_X9_62_id_ecPublicKey == EVP_PKEY_get_id(publicKey),
let ecKey = EVP_PKEY_get0_EC_KEY(publicKey),
NID_brainpoolP256r1 == EC_GROUP_get_curve_name(EC_KEY_get0_group(ecKey)),
let duplicate = EC_KEY_dup(ecKey) else {
Expand Down
2 changes: 1 addition & 1 deletion Sources/OpenSSL/EC/EllipticCurvePoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ extension EllipticCurvePoint {
try x.withUnsafeBignumPointer { xPtr in
try y.withUnsafeBignumPointer { yPtr in
try group.withUnsafeGroupPointer { groupPtr in
guard EC_POINT_get_affine_coordinates_GFp(groupPtr, point, xPtr, yPtr, nil) == 1
guard EC_POINT_get_affine_coordinates(groupPtr, point, xPtr, yPtr, nil) == 1
else {
throw OpenSSLError(name: "EC_POINT get affine coordinates GFp failed")
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/OpenSSL/EC/OpenSSLECGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ extension OpenSSLECGroup {
let number = field.withUnsafeBignumPointer { fieldPtr in
a.withUnsafeBignumPointer { aPtr in
b.withUnsafeBignumPointer { bPtr in
EC_GROUP_get_curve_GFp(self.curve, fieldPtr, aPtr, bPtr, nil)
EC_GROUP_get_curve(self.curve, fieldPtr, aPtr, bPtr, nil)
}
}
}
Expand Down
17 changes: 2 additions & 15 deletions Sources/OpenSSL/Hash/Hash.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
//
//

@_implementationOnly import COpenSSL
import CryptoKit
import Foundation

/// Hashing package
Expand All @@ -31,20 +31,7 @@ public extension Hash { // swiftlint:disable:this no_extension_access_modifier
/// - Parameter data: hash input
/// - Returns: SHA-256 hash
public static func hash(data: Data) -> Data {
let sha256 = UnsafeMutablePointer<SHA256_CTX>.allocate(capacity: 1)
defer {
sha256.deallocate()
}
var hash = [UInt8](repeating: 0x0, count: Int(SHA256_DIGEST_LENGTH))
SHA256_Init(sha256)
_ = data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) -> CInt in
guard let baseAddress = bytes.baseAddress else {
return CInt(0)
}
return SHA256_Update(sha256, baseAddress, bytes.count)
}
SHA256_Final(&hash, sha256)
return Data(hash)
Data(CryptoKit.SHA256.hash(data: data))
}

/// Hash the given string with SHA-256
Expand Down
Loading

0 comments on commit e1ef859

Please sign in to comment.