1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stddef.h>
6 #include <stdint.h>
7 #include <string.h>
8 
9 #include <crypto/secret.h>
10 #include <explicit-memory/bytes.h>
11 #include <fbl/algorithm.h>
12 #include <fbl/macros.h>
13 #include <fbl/unique_ptr.h>
14 #include <lib/fdio/debug.h>
15 #include <zircon/errors.h>
16 #include <zircon/status.h>
17 #include <zircon/syscalls.h>
18 #include <zircon/types.h>
19 
20 // See note in //zircon/third_party/ulib/uboringssl/rules.mk
21 #define BORINGSSL_NO_CXX
22 #include <openssl/mem.h>
23 
24 #define ZXDEBUG 0
25 
26 namespace crypto {
27 
28 // Public methods
29 
Secret()30 Secret::Secret() : buf_(nullptr), len_(0) {}
31 
~Secret()32 Secret::~Secret() {
33     Clear();
34 }
35 
Allocate(size_t len,uint8_t ** out)36 zx_status_t Secret::Allocate(size_t len, uint8_t** out) {
37     ZX_ASSERT(len != 0 && out);
38 
39     Clear();
40     fbl::AllocChecker ac;
41     buf_.reset(new (&ac) uint8_t[len]);
42     if (!ac.check()) {
43         xprintf("failed to allocate %zu bytes\n", len);
44         return ZX_ERR_NO_MEMORY;
45     }
46     memset(buf_.get(), 0, len);
47     len_ = len;
48 
49     *out = buf_.get();
50     return ZX_OK;
51 }
52 
Generate(size_t len)53 zx_status_t Secret::Generate(size_t len) {
54     ZX_ASSERT(len != 0);
55 
56     uint8_t* tmp = nullptr;
57     zx_status_t status = Allocate(len, &tmp);
58     if (status != ZX_OK) {
59         return status;
60     }
61 
62     zx_cprng_draw(buf_.get(), len);
63     return ZX_OK;
64 }
65 
Clear()66 void Secret::Clear() {
67     if (buf_) {
68         mandatory_memset(buf_.get(), 0, len_);
69     }
70     buf_.reset();
71     len_ = 0;
72 }
73 
74 } // namespace crypto
75