1 /*
2  * Copyright (C) 2021 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 #define TLOG_TAG "acvp"
18 
19 // NOTE: modulewrapper.h is not guarded against double inclusion and
20 // keymaster_ckdf.h uses it, so we need to include it before keymaster_ckdf.h
21 #include "modulewrapper.h"
22 
23 #include "acvp.h"
24 #include "keymaster_ckdf.h"
25 
26 #include <openssl/span.h>
27 #include <string.h>
28 #include <trusty_log.h>
29 #include "keymaster/android_keymaster_utils.h"
30 #include "keymaster/km_openssl/ckdf.h"
31 #include "openssl/rand.h"
32 
33 constexpr const char* kSharedHmacLabel = "KeymasterSharedMac";
34 constexpr size_t kContextLength = 32;
35 
KeymasterCKDF(const bssl::Span<const uint8_t> args[],bssl::acvp::ReplyCallback write_reply)36 bool KeymasterCKDF(const bssl::Span<const uint8_t> args[],
37                    bssl::acvp::ReplyCallback write_reply) {
38     const bssl::Span<const uint8_t> out_len_bytes = args[0];
39     const bssl::Span<const uint8_t> prf = args[1];
40     const bssl::Span<const uint8_t> counter_location = args[2];
41     const bssl::Span<const uint8_t> key_input = args[3];
42     const bssl::Span<const uint8_t> counter_len_bits = args[4];
43 
44     if (!StringEq(prf, "CMAC-AES128") && !StringEq(prf, "CMAC-AES256")) {
45         TLOGE("bad prf\n");
46         return false;
47     }
48     if (!StringEq(counter_location, "before fixed data")) {
49         TLOGE("bad counter_location\n");
50         return false;
51     }
52 
53     uint32_t out_len;
54     if (out_len_bytes.size() != sizeof(out_len)) {
55         TLOGE("bad out_len_bytes size\n");
56         return false;
57     }
58     memcpy(&out_len, out_len_bytes.data(), sizeof(out_len));
59 
60     uint32_t counter_len;
61     if (counter_len_bits.size() != sizeof(counter_len)) {
62         TLOGE("bad counter_len_bits size\n");
63         return false;
64     }
65     memcpy(&counter_len, counter_len_bits.data(), sizeof(counter_len));
66     if (counter_len != 32) {
67         TLOGE("bad counter_len_bits\n");
68         return false;
69     }
70 
71     keymaster::KeymasterKeyBlob key(key_input.data(), key_input.size());
72     keymaster::KeymasterKeyBlob output(out_len);
73 
74     keymaster::KeymasterBlob label(
75             reinterpret_cast<const uint8_t*>(kSharedHmacLabel),
76             strlen(kSharedHmacLabel));
77 
78     uint8_t context_buf[kContextLength];
79     auto ret = RAND_bytes(context_buf, sizeof(context_buf));
80     if (ret != 1) {
81         return false;
82     }
83     keymaster_blob_t context = {
84             context_buf,
85             sizeof(context_buf),
86     };
87 
88     auto ckdf_ret = ckdf(key, label, &context, 1, &output);
89     if (ckdf_ret != KM_ERROR_OK) {
90         TLOGE("ckdf returned code: %u\n", ckdf_ret);
91         return false;
92     }
93 
94     const uint32_t L = out_len * 8;  // bits
95     const uint32_t net_order_L = keymaster::hton(L);
96 
97     size_t fixed_data_size = label.data_length + 1 + context.data_length + 4;
98     std::unique_ptr<uint8_t[]> fixed_data(new (std::nothrow)
99                                                   uint8_t[fixed_data_size]);
100 
101     memcpy(fixed_data.get(), label.data, label.data_length);
102     fixed_data[label.data_length] = 0x00;
103     memcpy(&fixed_data[label.data_length + 1], context.data,
104            context.data_length);
105     memcpy(&fixed_data[label.data_length + 1 + context.data_length],
106            &net_order_L, 4);
107 
108     return write_reply({
109             bssl::Span<const uint8_t>(key.key_material, key.key_material_size),
110             bssl::Span<const uint8_t>(fixed_data.get(), fixed_data_size),
111             bssl::Span<const uint8_t>(output.key_material,
112                                       output.key_material_size),
113     });
114 }
115