• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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 #include <keymaster/key_blob_utils/integrity_assured_key_blob.h>
18 
19 #include <assert.h>
20 
21 #include <openssl/hmac.h>
22 #include <openssl/mem.h>
23 
24 #include <keymaster/android_keymaster_utils.h>
25 #include <keymaster/authorization_set.h>
26 #include <keymaster/km_openssl/openssl_err.h>
27 #include <keymaster/new>
28 
29 
30 namespace keymaster {
31 
32 static const uint8_t BLOB_VERSION = 0;
33 static const size_t HMAC_SIZE = 8;
34 static const char HMAC_KEY[] = "IntegrityAssuredBlob0";
35 
min(size_t a,size_t b)36 inline size_t min(size_t a, size_t b) {
37     if (a < b)
38         return a;
39     return b;
40 }
41 
42 class HmacCleanup {
43   public:
HmacCleanup(HMAC_CTX * ctx)44     explicit HmacCleanup(HMAC_CTX* ctx) : ctx_(ctx) {}
~HmacCleanup()45     ~HmacCleanup() { HMAC_CTX_cleanup(ctx_); }
46 
47   private:
48     HMAC_CTX* ctx_;
49 };
50 
ComputeHmac(const uint8_t * serialized_data,size_t serialized_data_size,const AuthorizationSet & hidden,uint8_t hmac[HMAC_SIZE])51 static keymaster_error_t ComputeHmac(const uint8_t* serialized_data, size_t serialized_data_size,
52                                      const AuthorizationSet& hidden, uint8_t hmac[HMAC_SIZE]) {
53     size_t hidden_bytes_size = hidden.SerializedSize();
54     UniquePtr<uint8_t[]> hidden_bytes(new (std::nothrow) uint8_t[hidden_bytes_size]);
55     if (!hidden_bytes.get())
56         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
57     hidden.Serialize(hidden_bytes.get(), hidden_bytes.get() + hidden_bytes_size);
58 
59     HMAC_CTX ctx;
60     HMAC_CTX_init(&ctx);
61     const EVP_MD* md = EVP_sha256();
62     if (!HMAC_Init_ex(&ctx, HMAC_KEY, sizeof(HMAC_KEY), md, nullptr /* engine */))
63         return TranslateLastOpenSslError();
64     HmacCleanup cleanup(&ctx);
65 
66     uint8_t tmp[EVP_MAX_MD_SIZE];
67     unsigned tmp_len;
68     if (!HMAC_Update(&ctx, serialized_data, serialized_data_size) ||
69         !HMAC_Update(&ctx, hidden_bytes.get(), hidden_bytes_size) ||  //
70         !HMAC_Final(&ctx, tmp, &tmp_len))
71         return TranslateLastOpenSslError();
72 
73     assert(tmp_len >= HMAC_SIZE);
74     memcpy(hmac, tmp, min(HMAC_SIZE, tmp_len));
75 
76     return KM_ERROR_OK;
77 }
78 
SerializeIntegrityAssuredBlob(const KeymasterKeyBlob & key_material,const AuthorizationSet & hidden,const AuthorizationSet & hw_enforced,const AuthorizationSet & sw_enforced,KeymasterKeyBlob * key_blob)79 keymaster_error_t SerializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_material,
80                                                 const AuthorizationSet& hidden,
81                                                 const AuthorizationSet& hw_enforced,
82                                                 const AuthorizationSet& sw_enforced,
83                                                 KeymasterKeyBlob* key_blob) {
84     size_t size = 1 /* version */ +                //
85                   key_material.SerializedSize() +  //
86                   hw_enforced.SerializedSize() +   //
87                   sw_enforced.SerializedSize() +   //
88                   HMAC_SIZE;
89 
90     if (!key_blob->Reset(size))
91         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
92 
93     uint8_t* p = key_blob->writable_data();
94     *p++ = BLOB_VERSION;
95     p = key_material.Serialize(p, key_blob->end());
96     p = hw_enforced.Serialize(p, key_blob->end());
97     p = sw_enforced.Serialize(p, key_blob->end());
98 
99     return ComputeHmac(key_blob->key_material, p - key_blob->key_material, hidden, p);
100 }
101 
DeserializeIntegrityAssuredBlob(const KeymasterKeyBlob & key_blob,const AuthorizationSet & hidden,KeymasterKeyBlob * key_material,AuthorizationSet * hw_enforced,AuthorizationSet * sw_enforced)102 keymaster_error_t DeserializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_blob,
103                                                   const AuthorizationSet& hidden,
104                                                   KeymasterKeyBlob* key_material,
105                                                   AuthorizationSet* hw_enforced,
106                                                   AuthorizationSet* sw_enforced) {
107     const uint8_t* p = key_blob.begin();
108     const uint8_t* end = key_blob.end();
109 
110     if (p > end || p + HMAC_SIZE > end)
111         return KM_ERROR_INVALID_KEY_BLOB;
112 
113     uint8_t computed_hmac[HMAC_SIZE];
114     keymaster_error_t error = ComputeHmac(key_blob.begin(), key_blob.key_material_size - HMAC_SIZE,
115                                           hidden, computed_hmac);
116     if (error != KM_ERROR_OK)
117         return error;
118 
119     if (CRYPTO_memcmp(key_blob.end() - HMAC_SIZE, computed_hmac, HMAC_SIZE) != 0)
120         return KM_ERROR_INVALID_KEY_BLOB;
121 
122     return DeserializeIntegrityAssuredBlob_NoHmacCheck(key_blob, key_material, hw_enforced,
123                                                        sw_enforced);
124 }
125 
DeserializeIntegrityAssuredBlob_NoHmacCheck(const KeymasterKeyBlob & key_blob,KeymasterKeyBlob * key_material,AuthorizationSet * hw_enforced,AuthorizationSet * sw_enforced)126 keymaster_error_t DeserializeIntegrityAssuredBlob_NoHmacCheck(const KeymasterKeyBlob& key_blob,
127                                                               KeymasterKeyBlob* key_material,
128                                                               AuthorizationSet* hw_enforced,
129                                                               AuthorizationSet* sw_enforced) {
130     const uint8_t* p = key_blob.begin();
131     const uint8_t* end = key_blob.end() - HMAC_SIZE;
132 
133     if (p > end)
134         return KM_ERROR_INVALID_KEY_BLOB;
135 
136     if (*p != BLOB_VERSION)
137         return KM_ERROR_INVALID_KEY_BLOB;
138     ++p;
139 
140     if (!key_material->Deserialize(&p, end) ||  //
141         !hw_enforced->Deserialize(&p, end) ||   //
142         !sw_enforced->Deserialize(&p, end))
143         return KM_ERROR_INVALID_KEY_BLOB;
144 
145     return KM_ERROR_OK;
146 }
147 
148 }  // namespace keymaster;
149