Home | History | Annotate | Download | only in keymaster
      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 
     25 namespace keymaster {
     26 
     27 const uint32_t CURRENT_BLOB_VERSION = 0;
     28 
     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 
     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 
     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