• 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/auth_encrypted_key_blob.h>
18 
19 #include <keymaster/android_keymaster_utils.h>
20 #include <keymaster/authorization_set.h>
21 #include <keymaster/key_blob_utils/ocb_utils.h>
22 #include <keymaster/logger.h>
23 
24 
25 namespace keymaster {
26 
27 const uint32_t CURRENT_BLOB_VERSION = 0;
28 
SerializeAuthEncryptedBlob(const KeymasterKeyBlob & encrypted_key_material,const AuthorizationSet & hw_enforced,const AuthorizationSet & sw_enforced,const Buffer & nonce,const Buffer & tag,KeymasterKeyBlob * key_blob)29 keymaster_error_t SerializeAuthEncryptedBlob(const KeymasterKeyBlob& encrypted_key_material,
30                                              const AuthorizationSet& hw_enforced,
31                                              const AuthorizationSet& sw_enforced,
32 
33                                              const Buffer& nonce, const Buffer& tag,
34                                              KeymasterKeyBlob* key_blob) {
35     size_t size = 1 /* version byte */ + nonce.SerializedSize() +
36                   encrypted_key_material.SerializedSize() + tag.SerializedSize() +
37                   hw_enforced.SerializedSize() + sw_enforced.SerializedSize();
38 
39     if (!key_blob->Reset(size))
40         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
41 
42     uint8_t* buf = key_blob->writable_data();
43     const uint8_t* end = key_blob->key_material + key_blob->key_material_size;
44 
45     *buf++ = CURRENT_BLOB_VERSION;
46     buf = nonce.Serialize(buf, end);
47     buf = encrypted_key_material.Serialize(buf, end);
48     buf = tag.Serialize(buf, end);
49     buf = hw_enforced.Serialize(buf, end);
50     buf = sw_enforced.Serialize(buf, end);
51     if (buf != key_blob->key_material + key_blob->key_material_size)
52         return KM_ERROR_UNKNOWN_ERROR;
53 
54     return KM_ERROR_OK;
55 }
56 
DeserializeUnversionedBlob(const KeymasterKeyBlob & key_blob,KeymasterKeyBlob * encrypted_key_material,AuthorizationSet * hw_enforced,AuthorizationSet * sw_enforced,Buffer * nonce,Buffer * tag)57 static keymaster_error_t DeserializeUnversionedBlob(const KeymasterKeyBlob& key_blob,
58                                                     KeymasterKeyBlob* encrypted_key_material,
59                                                     AuthorizationSet* hw_enforced,
60                                                     AuthorizationSet* sw_enforced, Buffer* nonce,
61                                                     Buffer* tag) {
62     const uint8_t* tmp = key_blob.key_material;
63     const uint8_t** buf_ptr = &tmp;
64     const uint8_t* end = tmp + key_blob.key_material_size;
65 
66     if (!nonce->reserve(OCB_NONCE_LENGTH) || !tag->reserve(OCB_TAG_LENGTH))
67         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
68 
69     if (!copy_from_buf(buf_ptr, end, nonce->peek_write(), OCB_NONCE_LENGTH) ||
70         !encrypted_key_material->Deserialize(buf_ptr, end) ||
71         !copy_from_buf(buf_ptr, end, tag->peek_write(), OCB_TAG_LENGTH) ||
72         !hw_enforced->Deserialize(buf_ptr, end) ||  //
73         !sw_enforced->Deserialize(buf_ptr, end)) {
74         LOG_D("Failed to deserialize unversioned blob (may be a HW-backed key)", 0);
75         return KM_ERROR_INVALID_KEY_BLOB;
76     }
77     if (!nonce->advance_write(OCB_NONCE_LENGTH) || !tag->advance_write(OCB_TAG_LENGTH))
78         return KM_ERROR_UNKNOWN_ERROR;
79     return KM_ERROR_OK;
80 }
81 
DeserializeAuthEncryptedBlob(const KeymasterKeyBlob & key_blob,KeymasterKeyBlob * encrypted_key_material,AuthorizationSet * hw_enforced,AuthorizationSet * sw_enforced,Buffer * nonce,Buffer * tag)82 keymaster_error_t DeserializeAuthEncryptedBlob(const KeymasterKeyBlob& key_blob,
83                                                KeymasterKeyBlob* encrypted_key_material,
84                                                AuthorizationSet* hw_enforced,
85                                                AuthorizationSet* sw_enforced, Buffer* nonce,
86                                                Buffer* tag) {
87     if (!key_blob.key_material || key_blob.key_material_size == 0)
88         return KM_ERROR_INVALID_KEY_BLOB;
89 
90     const uint8_t* tmp = key_blob.key_material;
91     const uint8_t** buf_ptr = &tmp;
92     const uint8_t* end = tmp + key_blob.key_material_size;
93 
94     if (end <= *buf_ptr)
95         return KM_ERROR_INVALID_KEY_BLOB;
96 
97     uint8_t version = *(*buf_ptr)++;
98     if (version != CURRENT_BLOB_VERSION ||  //
99         !nonce->Deserialize(buf_ptr, end) || nonce->available_read() != OCB_NONCE_LENGTH ||
100         !encrypted_key_material->Deserialize(buf_ptr, end) ||  //
101         !tag->Deserialize(buf_ptr, end) || tag->available_read() != OCB_TAG_LENGTH ||
102         !hw_enforced->Deserialize(buf_ptr, end) ||  //
103         !sw_enforced->Deserialize(buf_ptr, end)) {
104         // This blob failed to parse.  Either it's corrupted or it's a blob generated by an earlier
105         // version of keymaster using a previous blob format which did not include the version byte
106         // or the nonce or tag length fields.  So we try to parse it as that previous version.
107         //
108         // Note that it's not really a problem if we erronously parse a corrupted blob, because
109         // decryption will fail the authentication check.
110         //
111         // A bigger potential problem is: What if a valid unversioned blob appears to parse
112         // correctly as a versioned blob?  It would then be rejected during decryption, causing a
113         // valid key to become unusable.  If this is a disk encryption key, upgrading to a keymaster
114         // version with the new format would destroy the user's data.
115         //
116         // What is the probability that an unversioned key could be successfully parsed as a version
117         // 0 key?  The first 12 bytes of an unversioned key are the nonce, which, in the only
118         // keymaster version released with unversioned keys, is chosen randomly.  In order for an
119         // unversioned key to parse as a version 0 key, the following must be true about the first
120         // five of those random bytes:
121         //
122         // 1.  The first byte must be zero.  This will happen with probability 1/2^8.
123         //
124         // 2.  The second through fifth bytes must contain an unsigned integer value equal to
125         //     NONCE_LENGTH.  This will happen with probability 1/2^32.
126         //
127         // Based on those two checks alone, the probability of interpreting an unversioned blob as a
128         // version 0 blob is 1/2^40.  That's small enough to be negligible, but there are additional
129         // checks which lower it further.
130         LOG_D("Failed to deserialize versioned key blob.  Assuming unversioned.", 0);
131         return DeserializeUnversionedBlob(key_blob, encrypted_key_material, hw_enforced,
132                                           sw_enforced, nonce, tag);
133     }
134     return KM_ERROR_OK;
135 }
136 
137 }  // namespace keymaster
138