1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <stddef.h> 20 #include <optional> 21 #include <span> 22 #include <vector> 23 24 // From https://tools.ietf.org/html/rfc8152 25 constexpr int COSE_LABEL_ALG = 1; 26 constexpr int COSE_LABEL_KID = 4; 27 constexpr int COSE_LABEL_IV = 5; 28 constexpr int COSE_LABEL_KEY_KTY = 1; 29 constexpr int COSE_LABEL_KEY_ALG = 3; 30 constexpr int COSE_LABEL_KEY_SYMMETRIC_KEY = -1; 31 constexpr int COSE_TAG_ENCRYPT = 96; 32 constexpr int COSE_TAG_SIGN1 = 18; 33 constexpr int COSE_KEY_TYPE_SYMMETRIC = 4; 34 35 constexpr char COSE_CONTEXT_ENCRYPT[] = "Encrypt"; 36 constexpr char COSE_CONTEXT_ENC_RECIPIENT[] = "Enc_Recipient"; 37 38 // From "COSE Algorithms" registry 39 // See: RFC9053 or https://www.iana.org/assignments/cose/cose.txt 40 constexpr int COSE_ALG_A128GCM = 1; 41 constexpr int COSE_ALG_A256GCM = 2; 42 constexpr int COSE_ALG_ECDSA_256 = -7; 43 constexpr int COSE_ALG_ECDSA_384 = -35; 44 45 // Trusty-specific COSE constants 46 constexpr int COSE_LABEL_TRUSTY = -65537; 47 48 #ifdef APPLOADER_PACKAGE_CIPHER_A256 49 constexpr int COSE_VAL_CIPHER_ALG = COSE_ALG_A256GCM; 50 #else 51 constexpr int COSE_VAL_CIPHER_ALG = COSE_ALG_A128GCM; 52 #endif 53 54 #ifdef APPLOADER_PACKAGE_SIGN_P384 55 constexpr int COSE_VAL_SIGN_ALG = COSE_ALG_ECDSA_384; 56 #else 57 constexpr int COSE_VAL_SIGN_ALG = COSE_ALG_ECDSA_256; 58 #endif 59 60 constexpr size_t kAesGcmIvSize = 12; 61 constexpr size_t kAesGcmTagSize = 16; 62 #ifdef APPLOADER_PACKAGE_CIPHER_A256 63 constexpr size_t kAesGcmKeySize = 32; 64 #else 65 constexpr size_t kAesGcmKeySize = 16; 66 #endif 67 constexpr size_t kCoseEncryptArrayElements = 4; 68 69 using CoseByteView = std::span<const uint8_t>; 70 71 using GetKeyFn = 72 std::function<std::tuple<std::unique_ptr<uint8_t[]>, size_t>(uint8_t)>; 73 using DecryptFn = std::function<bool(CoseByteView key, 74 CoseByteView nonce, 75 uint8_t* encryptedData, 76 size_t encryptedDataSize, 77 CoseByteView additionalAuthenticatedData, 78 size_t* outPlaintextSize)>; 79 80 /** 81 * coseSetSilenceErrors() - Enable or disable the silencing of errors; 82 * @value: New value of the flag, %true if errors should be silenced. 83 * 84 * Return: the old value of the flag. 85 */ 86 bool coseSetSilenceErrors(bool value); 87 88 /** 89 * coseSignEcDsa() - Sign the given data using ECDSA and emit a COSE CBOR blob. 90 * @key: 91 * DER-encoded private key. 92 * @keyId: 93 * Key identifier, an unsigned 1-byte integer. 94 * @data: 95 * Block of data to sign and optionally encode inside the COSE signature 96 * structure. 97 * @protectedHeaders: 98 * Protected headers for the COSE structure. The function may add its own 99 * additional entries. 100 * @unprotectedHeaders: 101 * Unprotected headers for the COSE structure. The function may add its 102 * own additional entries. 103 * @detachContent: 104 * Whether to detach the data, i.e., not include @data in the returned 105 * ```COSE_Sign1``` structure. 106 * @tagged: 107 * Whether to return the tagged ```COSE_Sign1_Tagged``` or the untagged 108 * ```COSE_Sign1``` structure. 109 * 110 * This function signs a given block of data with ECDSA-SHA256 and encodes both 111 * the data and the signature using the COSE encoding from RFC 8152. The caller 112 * may specify whether the data is included or detached from the returned 113 * structure using the @detachContent parameter, as well as additional 114 * context-specific header values with the @protectedHeaders and 115 * @unprotectedHeaders parameters. 116 * 117 * Return: A vector containing the encoded ```COSE_Sign1``` structure if the 118 * signing algorithm succeeds, or a nullopt otherwise. 119 */ 120 std::optional<std::vector<uint8_t>> coseSignEcDsa( 121 const std::vector<uint8_t>& key, 122 uint8_t keyId, 123 const std::vector<uint8_t>& data, 124 const std::span<const uint8_t>& encodedProtectedHeaders, 125 std::span<const uint8_t>&, 126 bool detachContent, 127 bool tagged); 128 129 /** 130 * coseIsSigned() - Check if a block of bytes is a COSE signature emitted 131 * by coseSignEcDsa(). 132 * @data: Input data. 133 * @signatureLength: If not NULL, output argument where the total length 134 * of the signature structure will be stored. 135 * 136 * This function checks if the given data is a COSE signature structure 137 * emitted by coseSignEcDsa(), and returns the size of the signature if needed. 138 * 139 * Return: %true if the signature structure is valid, %false otherwise. 140 */ 141 bool coseIsSigned(CoseByteView data, size_t* signatureLength); 142 143 /** 144 * coseCheckEcDsaSignature() - Check if a given COSE signature structure is 145 * valid. 146 * @signatureCoseSign1: Input COSE signature structure. 147 * @detachedContent: Additional data to include in the signature. 148 * Corresponds to the @detachedContent parameter passed to 149 * coseSignEcDsa(). 150 * @publicKey: Public key in DER encoding. 151 * 152 * Returns: %true if the signature verification passes, %false otherwise. 153 */ 154 bool coseCheckEcDsaSignature(const std::vector<uint8_t>& signatureCoseSign1, 155 const std::vector<uint8_t>& detachedContent, 156 const std::vector<uint8_t>& publicKey); 157 158 /** 159 * strictCheckEcDsaSignature() - Check a given COSE signature in strict mode. 160 * @packageStart: Pointer to the start of the signed input package. 161 * @packageSize: Size of the signed input package. 162 * @keyFn: Function to call with a key id that returns the public 163 * key for that id. 164 * @outPackageStart: If not NULL, output argument where the start of the 165 * payload will be stored. 166 * @outPackageSize: If not NULL, output argument where the size of the 167 * payload will be stored. 168 * 169 * This function performs a strict verification of the COSE signature of a 170 * package. Instead of parsing the COSE structure, the function compares the 171 * raw bytes against a set of exact patterns, and fails if the bytes do not 172 * match. The actual signature and payload are also assumed to start at fixed 173 * offsets from @packageStart. 174 * 175 * Returns: %true if the signature verification passes, %false otherwise. 176 */ 177 bool strictCheckEcDsaSignature(const uint8_t* packageStart, 178 size_t packageSize, 179 GetKeyFn keyFn, 180 const uint8_t** outPackageStart, 181 size_t* outPackageSize); 182 183 /** 184 * coseEncryptAes128GcmKeyWrap() - Encrypt a block of data using AES-GCM 185 * and a randomly-generated wrapped CEK. 186 * @key: 187 * Key encryption key (KEK), 16 or 32 bytes in size. 188 * @keyId: 189 * Key identifier for the KEK, an unsigned 1-byte integer. 190 * @data: 191 * Input data to encrypt. 192 * @externalAad: 193 * Additional authentication data to pass to AES-GCM. 194 * @protectedHeaders: 195 * Protected headers for the COSE structure. The function may add its own 196 * additional entries. 197 * @unprotectedHeaders: 198 * Unprotected headers for the COSE structure. The function may add its 199 * own additional entries. 200 * @tagged: 201 * Whether to return the tagged ```COSE_Encrypt_Tagged``` or the untagged 202 * ```COSE_Encrypt``` structure. 203 * 204 * This function generates a random key content encryption key (CEK) and wraps 205 * it using AES-GCM, then encrypts a given block of data with AES-GCM 206 * with the wrapped CEK and encodes both the data and CEK using the COSE 207 * encoding from RFC 8152. 208 * 209 * The key length must be 128 or 256 depending on build-time configuration. 210 * The IV and Tag lengths are fixed (128-bit and 96-bits respectively, see 211 * ```kAesGcmIvSize``` and ```kAesGcmTagSize```). 212 * 213 * The caller may specify additional context-specific header values with the 214 * @protectedHeaders and @unprotectedHeaders parameters. 215 * 216 * Return: A vector of bytes containing the encoded ```COSE_Encrypt``` structure 217 * if the encryption succeeds, or a nullopt otherwise. 218 */ 219 std::optional<std::vector<uint8_t>> coseEncryptAesGcmKeyWrap( 220 const std::vector<uint8_t>& key, 221 uint8_t keyId, 222 const CoseByteView& data, 223 const std::vector<uint8_t>& externalAad, 224 const std::vector<uint8_t>& encodedProtectedHeaders, 225 const CoseByteView& unprotectedHeaders, 226 bool tagged); 227 228 /** 229 * coseDecryptAesGcmKeyWrapInPlace() - Decrypt a block of data containing a 230 * wrapped key using AES-GCM. 231 * @item: CBOR item containing a ```COSE_Encrypt``` structure. 232 * @keyFn: Function to call with a key id that returns the key 233 * encryption key (KEK) for that id. 234 * @externalAad: Additional authentication data to pass to AES-GCM. 235 * @checkTag: Whether to check the CBOR semantic tag of @item. 236 * @outPackageStart: The output argument where the start of the 237 * payload will be stored. Must not be %NULL. 238 * @outPackageSize: The output argument where the size of the 239 * payload will be stored. Must not be %NULL. 240 * 241 * This function decrypts a ciphertext encrypted with AES-GCM and encoded 242 * in a ```COSE_Encrypt0_Tagged``` structure. The function performs in-place 243 * decryption and overwrites the ciphertext with the plaintext, and returns 244 * the pointer and size of the plaintext in @outPackageStart and 245 * @outPackageSize, respectively. 246 * The key length is 128 or 256 depending on build-time configuration. The IV 247 * and Tag lengths are fixed (128-bit and 96-bits respectively). 248 * 249 * Returns: %true if the decryption succeeds, %false otherwise. 250 */ 251 bool coseDecryptAesGcmKeyWrapInPlace(const CoseByteView& item, 252 GetKeyFn keyFn, 253 const std::vector<uint8_t>& externalAad, 254 bool checkTag, 255 const uint8_t** outPackageStart, 256 size_t* outPackageSize, 257 DecryptFn decryptFn = DecryptFn()); 258 259 /** 260 * coseGetCipherAlg - Get the name of the cipher for package encryption. 261 * Returns: A pointer to a static string describing the cipher. 262 */ 263 const char* coseGetCipherAlg(void); 264 265 /** 266 * coseGetSigningDsa() - Get the name of the signing Digital Signature Algo. 267 * Returns: A pointer to a static string describing the signing method. 268 */ 269 const char* coseGetSigningDsa(void); 270