blob: 26c8a1b2957b212a0492c266a61e29ab8ee8774b [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <crypto/secret.h>
#include <explicit-memory/bytes.h>
#include <fbl/algorithm.h>
#include <fbl/macros.h>
#include <fbl/unique_ptr.h>
#include <lib/fdio/debug.h>
#include <openssl/mem.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>
#define ZXDEBUG 0
namespace crypto {
// Public methods
Secret::Secret() : buf_(nullptr), len_(0) {}
Secret::~Secret() {
Clear();
}
zx_status_t Secret::Allocate(size_t len, uint8_t** out) {
ZX_DEBUG_ASSERT(len != 0 && out);
Clear();
fbl::AllocChecker ac;
buf_.reset(new (&ac) uint8_t[len]);
if (!ac.check()) {
xprintf("failed to allocate %zu bytes\n", len);
return ZX_ERR_NO_MEMORY;
}
memset(buf_.get(), 0, len);
len_ = len;
*out = buf_.get();
return ZX_OK;
}
zx_status_t Secret::Generate(size_t len) {
ZX_DEBUG_ASSERT(len != 0);
zx_status_t rc;
uint8_t* tmp;
if ((rc = Allocate(len, &tmp)) != ZX_OK) {
return rc;
}
uint8_t* ptr = buf_.get();
while (len != 0) {
size_t n = fbl::min(len, static_cast<size_t>(ZX_CPRNG_DRAW_MAX_LEN));
if ((rc = zx_cprng_draw_new(ptr, n)) != ZX_OK) {
xprintf("zx_cprng_draw of %zu bytes failed: %s", n, zx_status_get_string(rc));
return rc;
}
ptr += n;
len -= n;
}
return ZX_OK;
}
void Secret::Clear() {
if (buf_) {
mandatory_memset(buf_.get(), 0, len_);
}
buf_.reset();
len_ = 0;
}
} // namespace crypto