File: ChaCha20CTR_boring.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (68 lines) | stat: -rw-r--r-- 3,196 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftCrypto open source project
//
// Copyright (c) 2023 Apple Inc. and the SwiftCrypto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.md for the list of SwiftCrypto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

@_implementationOnly import CCryptoBoringSSL
@_implementationOnly import CCryptoBoringSSLShims
import Crypto
@_implementationOnly import CryptoBoringWrapper
import Foundation

enum OpenSSLChaCha20CTRImpl {
    static func encrypt<M: DataProtocol, N: ContiguousBytes>(key: SymmetricKey, message: M, counter: UInt32, nonce: N) throws -> Data {
        guard key.bitCount == Insecure.ChaCha20CTR.keyBitsCount else {
            throw CryptoKitError.incorrectKeySize
        }

        // If our message, conforming to DataProtocol, happens to be allocated contiguously in memory, then we can grab the first, and only, contiguous region and operate on it
        if message.regions.count == 1 {
            return self._encryptContiguous(key: key, message: message.regions.first!, counter: counter, nonce: nonce)
        } else {
            // Otherwise we need to consolidate the noncontiguous bytes by instantiating an Array<UInt8>
            let contiguousMessage = Array(message)
            return self._encryptContiguous(key: key, message: contiguousMessage, counter: counter, nonce: nonce)
        }
    }

    /// A fast-path for encrypting contiguous data. Also inlinable to gain specialization information.
    @inlinable
    static func _encryptContiguous<Plaintext: ContiguousBytes, Nonce: ContiguousBytes>(key: SymmetricKey, message: Plaintext, counter: UInt32, nonce: Nonce) -> Data {
        key.withUnsafeBytes { keyPtr in
            nonce.withUnsafeBytes { noncePtr in
                message.withUnsafeBytes { plaintextPtr in
                    // We bind all three pointers here. These binds are not technically safe, but because we
                    // know the pointers don't persist they can't violate the aliasing rules. We really
                    // want a "with memory rebound" function but we don't have it yet.
                    let keyBytes = keyPtr.bindMemory(to: UInt8.self)
                    let nonceBytes = noncePtr.bindMemory(to: UInt8.self)
                    let plaintext = plaintextPtr.bindMemory(to: UInt8.self)

                    var ciphertext = Data(repeating: 0, count: plaintext.count)

                    ciphertext.withUnsafeMutableBytes { ciphertext in
                        CCryptoBoringSSL_CRYPTO_chacha_20(
                            ciphertext.baseAddress,
                            plaintext.baseAddress,
                            plaintext.count,
                            keyBytes.baseAddress,
                            nonceBytes.baseAddress,
                            counter
                        )
                    }

                    return ciphertext
                }
            }
        }
    }
}