blob: b73766fccf702e3f0891e4dac1477fb55e9256fc [file] [log] [blame]
/*
* Copyright (c) 2008 The Native Client Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* NaCl Service Runtime. Secure RNG implementation.
*/
#include <windows.h>
/* Work around a clang-cl bug: SecureZeroMemory() below uses __stosb() but
* windows.h only declares that intrinsic and then uses `#pragma intrinsic` for
* it. clang-cl doesn't implement `#pragma intrinsic` yet; it instead defines
* the function as an always-inline symbol in its intrin.h.
* TODO(thakis): Remove this once http://llvm.org/PR19898 is fixed.
*/
#include <intrin.h>
/*
* #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See
* the "Community Additions" comment on MSDN here:
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx
*/
#define SystemFunction036 NTAPI SystemFunction036
#include <NTSecAPI.h>
#undef SystemFunction036
#include "native_client/src/shared/platform/nacl_log.h"
#include "native_client/src/shared/platform/nacl_secure_random.h"
static void NaClSecureRngDtor(struct NaClSecureRngIf *vself);
static uint8_t NaClSecureRngGenByte(struct NaClSecureRngIf *vself);
static struct NaClSecureRngIfVtbl const kNaClSecureRngVtbl = {
NaClSecureRngDtor,
NaClSecureRngGenByte,
NaClSecureRngDefaultGenUint32,
NaClSecureRngDefaultGenBytes,
NaClSecureRngDefaultUniform,
};
void NaClSecureRngModuleInit(void) {
return;
}
void NaClSecureRngModuleFini(void) {
return;
}
int NaClSecureRngCtor(struct NaClSecureRng *self) {
self->base.vtbl = &kNaClSecureRngVtbl;
self->nvalid = 0;
return 1;
}
int NaClSecureRngTestingCtor(struct NaClSecureRng *self,
uint8_t *seed_material,
size_t seed_bytes) {
UNREFERENCED_PARAMETER(seed_material);
UNREFERENCED_PARAMETER(seed_bytes);
self->base.vtbl = NULL;
self->nvalid = 0;
return 0;
}
static void NaClSecureRngDtor(struct NaClSecureRngIf *vself) {
struct NaClSecureRng *self = (struct NaClSecureRng *) vself;
SecureZeroMemory(self->buf, sizeof self->buf);
vself->vtbl = NULL;
return;
}
static void NaClSecureRngFilbuf(struct NaClSecureRng *self) {
if (!RtlGenRandom(self->buf, sizeof self->buf)) {
NaClLog(LOG_FATAL, "RtlGenRandom failed: error 0x%x\n", GetLastError());
}
self->nvalid = sizeof self->buf;
}
static uint8_t NaClSecureRngGenByte(struct NaClSecureRngIf *vself) {
struct NaClSecureRng *self = (struct NaClSecureRng *) vself;
if (0 > self->nvalid) {
NaClLog(LOG_FATAL,
"NaClSecureRngGenByte: illegal buffer state, nvalid = %d\n",
self->nvalid);
}
if (0 == self->nvalid) {
NaClSecureRngFilbuf(self);
}
return self->buf[--self->nvalid];
}