1 /* 2 * Copyright (C) 2015 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 #ifndef KEYSTORE_BLOB_H_ 18 #define KEYSTORE_BLOB_H_ 19 20 #include <stdint.h> 21 22 #include <openssl/aes.h> 23 #include <openssl/md5.h> 24 25 #include <keystore/keystore.h> 26 27 #define VALUE_SIZE 32768 28 29 /* Here is the file format. There are two parts in blob.value, the secret and 30 * the description. The secret is stored in ciphertext, and its original size 31 * can be found in blob.length. The description is stored after the secret in 32 * plaintext, and its size is specified in blob.info. The total size of the two 33 * parts must be no more than VALUE_SIZE bytes. The first field is the version, 34 * the second is the blob's type, and the third byte is flags. Fields other 35 * than blob.info, blob.length, and blob.value are modified by encryptBlob() 36 * and decryptBlob(). Thus they should not be accessed from outside. */ 37 38 /* ** Note to future implementors of encryption: ** 39 * Currently this is the construction: 40 * metadata || Enc(MD5(data) || data) 41 * 42 * This should be the construction used for encrypting if re-implementing: 43 * 44 * Derive independent keys for encryption and MAC: 45 * Kenc = AES_encrypt(masterKey, "Encrypt") 46 * Kmac = AES_encrypt(masterKey, "MAC") 47 * 48 * Store this: 49 * metadata || AES_CTR_encrypt(Kenc, rand_IV, data) || 50 * HMAC(Kmac, metadata || Enc(data)) 51 */ 52 struct __attribute__((packed)) blob { 53 uint8_t version; 54 uint8_t type; 55 uint8_t flags; 56 uint8_t info; 57 uint8_t vector[AES_BLOCK_SIZE]; 58 uint8_t encrypted[0]; // Marks offset to encrypted data. 59 uint8_t digest[MD5_DIGEST_LENGTH]; 60 uint8_t digested[0]; // Marks offset to digested data. 61 int32_t length; // in network byte order when encrypted 62 uint8_t value[VALUE_SIZE + AES_BLOCK_SIZE]; 63 }; 64 65 static const uint8_t CURRENT_BLOB_VERSION = 2; 66 67 typedef enum { 68 TYPE_ANY = 0, // meta type that matches anything 69 TYPE_GENERIC = 1, 70 TYPE_MASTER_KEY = 2, 71 TYPE_KEY_PAIR = 3, 72 TYPE_KEYMASTER_10 = 4, 73 } BlobType; 74 75 class Entropy; 76 77 class Blob { 78 public: 79 Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength, 80 BlobType type); 81 Blob(blob b); 82 83 Blob(); 84 getValue()85 const uint8_t* getValue() const { return mBlob.value; } 86 getLength()87 int32_t getLength() const { return mBlob.length; } 88 getInfo()89 const uint8_t* getInfo() const { return mBlob.value + mBlob.length; } getInfoLength()90 uint8_t getInfoLength() const { return mBlob.info; } 91 getVersion()92 uint8_t getVersion() const { return mBlob.version; } 93 94 bool isEncrypted() const; 95 void setEncrypted(bool encrypted); 96 isFallback()97 bool isFallback() const { return mBlob.flags & KEYSTORE_FLAG_FALLBACK; } 98 void setFallback(bool fallback); 99 setVersion(uint8_t version)100 void setVersion(uint8_t version) { mBlob.version = version; } getType()101 BlobType getType() const { return BlobType(mBlob.type); } setType(BlobType type)102 void setType(BlobType type) { mBlob.type = uint8_t(type); } 103 104 ResponseCode writeBlob(const char* filename, AES_KEY* aes_key, State state, Entropy* entropy); 105 ResponseCode readBlob(const char* filename, AES_KEY* aes_key, State state); 106 107 private: 108 struct blob mBlob; 109 }; 110 111 #endif // KEYSTORE_BLOB_H_ 112