Line data Source code
1 : /**
2 : * The MIT License (MIT)
3 : *
4 : * Copyright (c) 2021 RSK Labs Ltd
5 : *
6 : * Permission is hereby granted, free of charge, to any person obtaining a copy
7 : * of this software and associated documentation files (the "Software"), to
8 : * deal in the Software without restriction, including without limitation the
9 : * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 : * sell copies of the Software, and to permit persons to whom the Software is
11 : * furnished to do so, subject to the following conditions:
12 : *
13 : * The above copyright notice and this permission notice shall be included in
14 : * all copies or substantial portions of the Software.
15 : *
16 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 : * IN THE SOFTWARE.
23 : */
24 :
25 : #include "migrate.h"
26 :
27 : #include <string.h>
28 : #include <openenclave/corelibc/stdlib.h>
29 : #include "hal/seed.h"
30 : #include "hal/access.h"
31 : #include "hal/log.h"
32 : #include "pin_policy.h"
33 : #include "defs.h"
34 : #include "aes_gcm.h"
35 :
36 : #define EXPORT_SIZE (SEED_LENGTH + MAX_PIN_LENGTH)
37 :
38 6 : bool migrate_export(uint8_t* key,
39 : size_t key_size,
40 : uint8_t* out,
41 : size_t* out_size) {
42 6 : bool retval = false;
43 6 : uint8_t* cleartext = NULL;
44 :
45 : // Sizes check
46 6 : if (!aes_gcm_get_encrypted_size(EXPORT_SIZE)) {
47 : LOG("Migration export error: export size too big\n");
48 0 : goto migrate_export_exit;
49 : }
50 6 : if (*out_size < aes_gcm_get_encrypted_size(EXPORT_SIZE)) {
51 : LOG("Migration export error: output buffer too small\n");
52 1 : goto migrate_export_exit;
53 : }
54 :
55 : // Buffers
56 5 : cleartext = oe_malloc(EXPORT_SIZE);
57 5 : if (!cleartext) {
58 : LOG("Migration export error: unable to allocate memory\n");
59 0 : goto migrate_export_exit;
60 : }
61 :
62 : // Export
63 5 : explicit_bzero(cleartext, EXPORT_SIZE);
64 5 : uint8_t* tmp = cleartext;
65 5 : size_t tmp_size = EXPORT_SIZE;
66 5 : size_t exp_size = 0;
67 5 : if (!seed_output_USE_FROM_EXPORT_ONLY(tmp, &tmp_size)) {
68 : LOG("Migration export error: unable to export seed\n");
69 1 : goto migrate_export_exit;
70 : }
71 4 : tmp += tmp_size;
72 4 : exp_size += tmp_size;
73 4 : tmp_size = EXPORT_SIZE - tmp_size;
74 4 : if (!access_output_password_USE_FROM_EXPORT_ONLY(tmp, &tmp_size)) {
75 : LOG("Migration export error: unable to export password\n");
76 1 : goto migrate_export_exit;
77 : }
78 3 : exp_size += tmp_size;
79 3 : if (exp_size != EXPORT_SIZE) {
80 : LOG("Migration export error: unexpected exported size\n");
81 1 : goto migrate_export_exit;
82 : }
83 :
84 : // Encrypt and output
85 2 : explicit_bzero(out, *out_size);
86 2 : if (!aes_gcm_encrypt(
87 : key, key_size, cleartext, EXPORT_SIZE, out, out_size)) {
88 : LOG("Migration export error: error encrypting DB\n");
89 1 : goto migrate_export_exit;
90 : }
91 1 : if (*out_size != aes_gcm_get_encrypted_size(EXPORT_SIZE)) {
92 : LOG("Migration export error: unexpected encrypted DB size\n");
93 0 : goto migrate_export_exit;
94 : }
95 1 : explicit_bzero(cleartext, EXPORT_SIZE);
96 1 : retval = true;
97 :
98 : LOG("Migration exported DB\n");
99 :
100 6 : migrate_export_exit:
101 6 : if (cleartext) {
102 5 : explicit_bzero(cleartext, EXPORT_SIZE);
103 5 : oe_free(cleartext);
104 5 : cleartext = NULL;
105 : }
106 6 : return retval;
107 : }
108 :
109 5 : bool migrate_import(uint8_t* key,
110 : size_t key_size,
111 : uint8_t* in,
112 : size_t in_size) {
113 5 : bool retval = false;
114 5 : uint8_t* cleartext = NULL;
115 : size_t cleartext_size;
116 :
117 : // Sizes check
118 5 : if (!aes_gcm_get_encrypted_size(EXPORT_SIZE)) {
119 : LOG("Migration import error: export size too big\n");
120 0 : goto migrate_import_exit;
121 : }
122 5 : if (in_size < aes_gcm_get_encrypted_size(EXPORT_SIZE)) {
123 : LOG("Migration import error: input buffer too small\n");
124 1 : goto migrate_import_exit;
125 : }
126 :
127 : // Buffers
128 4 : cleartext_size = EXPORT_SIZE;
129 4 : cleartext = oe_malloc(cleartext_size);
130 4 : if (!cleartext) {
131 : LOG("Migration import error: unable to allocate memory\n");
132 0 : goto migrate_import_exit;
133 : }
134 :
135 : // Decrypt
136 4 : if (!aes_gcm_decrypt(
137 : key, key_size, in, in_size, cleartext, &cleartext_size)) {
138 : LOG("Migration import error: error decrypting DB\n");
139 1 : goto migrate_import_exit;
140 : }
141 3 : if (cleartext_size != EXPORT_SIZE) {
142 : LOG("Migration import error: invalid DB\n");
143 0 : goto migrate_import_exit;
144 : }
145 :
146 : // Import
147 3 : if (!seed_set_USE_FROM_EXPORT_ONLY(cleartext, SEED_LENGTH)) {
148 : LOG("Migration import error: unable to import seed\n");
149 1 : goto migrate_import_exit;
150 : }
151 2 : if (!access_set_password((char*)(cleartext + SEED_LENGTH),
152 2 : cleartext_size - SEED_LENGTH)) {
153 : LOG("Migration import error: unable to import password\n");
154 1 : goto migrate_import_exit;
155 : }
156 :
157 1 : explicit_bzero(cleartext, cleartext_size);
158 1 : retval = true;
159 : LOG("Migration imported DB\n");
160 :
161 5 : migrate_import_exit:
162 : // Wipe everything in case something fails
163 5 : if (!retval) {
164 : LOG("Migration import: preemptively wiping system\n");
165 4 : seed_wipe();
166 4 : access_wipe();
167 : }
168 5 : if (cleartext) {
169 4 : explicit_bzero(cleartext, EXPORT_SIZE);
170 4 : oe_free(cleartext);
171 4 : cleartext = NULL;
172 : }
173 5 : return retval;
174 : }
|