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 "auth_encrypted_key_blob.h"
18
19#include <keymaster/android_keymaster_utils.h>
20#include <keymaster/authorization_set.h>
21#include <keymaster/logger.h>
22
23#include "ocb_utils.h"
24
25namespace keymaster {
26
27const uint32_t CURRENT_BLOB_VERSION = 0;
28
29keymaster_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
57static 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
82keymaster_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