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 :
58 : // Export
59 5 : explicit_bzero(cleartext, EXPORT_SIZE);
60 5 : uint8_t* tmp = cleartext;
61 5 : size_t tmp_size = EXPORT_SIZE;
62 5 : size_t exp_size = 0;
63 5 : if (!seed_output_USE_FROM_EXPORT_ONLY(tmp, &tmp_size)) {
64 : LOG("Migration export error: unable to export seed\n");
65 1 : goto migrate_export_exit;
66 : }
67 4 : tmp += tmp_size;
68 4 : exp_size += tmp_size;
69 4 : tmp_size = EXPORT_SIZE - tmp_size;
70 4 : if (!access_output_password_USE_FROM_EXPORT_ONLY(tmp, &tmp_size)) {
71 : LOG("Migration export error: unable to export password\n");
72 1 : goto migrate_export_exit;
73 : }
74 3 : exp_size += tmp_size;
75 3 : if (exp_size != EXPORT_SIZE) {
76 : LOG("Migration export error: unexpected exported size\n");
77 1 : goto migrate_export_exit;
78 : }
79 :
80 : // Encrypt and output
81 2 : explicit_bzero(out, *out_size);
82 2 : if (!aes_gcm_encrypt(
83 : key, key_size, cleartext, EXPORT_SIZE, out, out_size)) {
84 : LOG("Migration export error: error encrypting DB\n");
85 1 : goto migrate_export_exit;
86 : }
87 1 : if (*out_size != aes_gcm_get_encrypted_size(EXPORT_SIZE)) {
88 : LOG("Migration export error: unexpected encrypted DB size\n");
89 0 : goto migrate_export_exit;
90 : }
91 1 : explicit_bzero(cleartext, EXPORT_SIZE);
92 1 : retval = true;
93 :
94 : LOG("Migration exported DB\n");
95 :
96 6 : migrate_export_exit:
97 6 : if (cleartext) {
98 5 : explicit_bzero(cleartext, EXPORT_SIZE);
99 5 : oe_free(cleartext);
100 5 : cleartext = NULL;
101 : }
102 6 : return retval;
103 : }
104 :
105 5 : bool migrate_import(uint8_t* key,
106 : size_t key_size,
107 : uint8_t* in,
108 : size_t in_size) {
109 5 : bool retval = false;
110 5 : uint8_t* cleartext = NULL;
111 : size_t cleartext_size;
112 :
113 : // Sizes check
114 5 : if (!aes_gcm_get_encrypted_size(EXPORT_SIZE)) {
115 : LOG("Migration import error: export size too big\n");
116 0 : goto migrate_import_exit;
117 : }
118 5 : if (in_size < aes_gcm_get_encrypted_size(EXPORT_SIZE)) {
119 : LOG("Migration import error: input buffer too small\n");
120 1 : goto migrate_import_exit;
121 : }
122 :
123 : // Buffers
124 4 : cleartext_size = EXPORT_SIZE;
125 4 : cleartext = oe_malloc(cleartext_size);
126 :
127 : // Decrypt
128 4 : if (!aes_gcm_decrypt(
129 : key, key_size, in, in_size, cleartext, &cleartext_size)) {
130 : LOG("Migration import error: error decrypting DB\n");
131 1 : goto migrate_import_exit;
132 : }
133 3 : if (cleartext_size != EXPORT_SIZE) {
134 : LOG("Migration import error: invalid DB\n");
135 0 : goto migrate_import_exit;
136 : }
137 :
138 : // Import
139 3 : if (!seed_set_USE_FROM_EXPORT_ONLY(cleartext, SEED_LENGTH)) {
140 : LOG("Migration import error: unable to import seed\n");
141 1 : goto migrate_import_exit;
142 : }
143 2 : if (!access_set_password((char*)(cleartext + SEED_LENGTH),
144 2 : cleartext_size - SEED_LENGTH)) {
145 : LOG("Migration import error: unable to import password\n");
146 1 : goto migrate_import_exit;
147 : }
148 :
149 1 : explicit_bzero(cleartext, cleartext_size);
150 1 : retval = true;
151 : LOG("Migration imported DB\n");
152 :
153 5 : migrate_import_exit:
154 : // Wipe everything in case something fails
155 5 : if (!retval) {
156 : LOG("Migration import: preemptively wiping system\n");
157 4 : seed_wipe();
158 4 : access_wipe();
159 : }
160 5 : if (cleartext) {
161 4 : explicit_bzero(cleartext, EXPORT_SIZE);
162 4 : oe_free(cleartext);
163 4 : cleartext = NULL;
164 : }
165 5 : return retval;
166 : }
|