1296047Soshogbo/*-
2296047Soshogbo * Copyright (c) 2013 The FreeBSD Foundation
3296047Soshogbo * All rights reserved.
4296047Soshogbo *
5296047Soshogbo * This software was developed by Pawel Jakub Dawidek under sponsorship from
6296047Soshogbo * the FreeBSD Foundation.
7296047Soshogbo *
8296047Soshogbo * Redistribution and use in source and binary forms, with or without
9296047Soshogbo * modification, are permitted provided that the following conditions
10296047Soshogbo * are met:
11296047Soshogbo * 1. Redistributions of source code must retain the above copyright
12296047Soshogbo *    notice, this list of conditions and the following disclaimer.
13296047Soshogbo * 2. Redistributions in binary form must reproduce the above copyright
14296047Soshogbo *    notice, this list of conditions and the following disclaimer in the
15296047Soshogbo *    documentation and/or other materials provided with the distribution.
16296047Soshogbo *
17296047Soshogbo * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18296047Soshogbo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19296047Soshogbo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20296047Soshogbo * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21296047Soshogbo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22296047Soshogbo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23296047Soshogbo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24296047Soshogbo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25296047Soshogbo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26296047Soshogbo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27296047Soshogbo * SUCH DAMAGE.
28296047Soshogbo */
29296047Soshogbo
30296047Soshogbo#include <sys/cdefs.h>
31296047Soshogbo__FBSDID("$FreeBSD$");
32296047Soshogbo
33296047Soshogbo#include <sys/nv.h>
34296047Soshogbo
35296047Soshogbo#include <assert.h>
36296047Soshogbo#include <errno.h>
37296047Soshogbo#include <stdio.h>
38296047Soshogbo#include <stdlib.h>
39296047Soshogbo#include <string.h>
40296047Soshogbo
41296047Soshogbo#include <libcasper.h>
42296047Soshogbo#include <libcasper_service.h>
43296047Soshogbo
44296047Soshogbo#include "cap_random.h"
45296047Soshogbo
46296047Soshogbo#define	MAXSIZE	(1024 * 1024)
47296047Soshogbo
48296047Soshogboint
49296047Soshogbocap_random_buf(cap_channel_t *chan, void *buf, size_t nbytes)
50296047Soshogbo{
51296047Soshogbo	nvlist_t *nvl;
52296047Soshogbo	const void *randbuf;
53296047Soshogbo	uint8_t *ptr;
54296047Soshogbo	size_t left, randbufsize;
55296047Soshogbo
56296047Soshogbo	left = nbytes;
57296047Soshogbo	ptr = buf;
58296047Soshogbo
59296047Soshogbo	while (left > 0) {
60296047Soshogbo		nvl = nvlist_create(0);
61296047Soshogbo		nvlist_add_string(nvl, "cmd", "generate");
62296047Soshogbo		nvlist_add_number(nvl, "size",
63296047Soshogbo		    (uint64_t)(left > MAXSIZE ? MAXSIZE : left));
64296047Soshogbo		nvl = cap_xfer_nvlist(chan, nvl, 0);
65296047Soshogbo		if (nvl == NULL)
66296047Soshogbo			return (-1);
67296047Soshogbo		if (nvlist_get_number(nvl, "error") != 0) {
68296047Soshogbo			errno = (int)nvlist_get_number(nvl, "error");
69296047Soshogbo			nvlist_destroy(nvl);
70296047Soshogbo			return (-1);
71296047Soshogbo		}
72296047Soshogbo
73296047Soshogbo		randbuf = nvlist_get_binary(nvl, "data", &randbufsize);
74296047Soshogbo		memcpy(ptr, randbuf, randbufsize);
75296047Soshogbo
76296047Soshogbo		nvlist_destroy(nvl);
77296047Soshogbo
78296047Soshogbo		ptr += randbufsize;
79296047Soshogbo		assert(left >= randbufsize);
80296047Soshogbo		left -= randbufsize;
81296047Soshogbo	}
82296047Soshogbo
83296047Soshogbo	return (0);
84296047Soshogbo}
85296047Soshogbo
86296047Soshogbo/*
87296047Soshogbo * Service functions.
88296047Soshogbo */
89296047Soshogbo
90296047Soshogbostatic int
91296047Soshogborandom_command(const char *cmd, const nvlist_t *limits __unused,
92296047Soshogbo    nvlist_t *nvlin, nvlist_t *nvlout)
93296047Soshogbo{
94296047Soshogbo	void *data;
95296047Soshogbo	size_t size;
96296047Soshogbo
97296047Soshogbo	if (strcmp(cmd, "generate") != 0)
98296047Soshogbo		return (EINVAL);
99296047Soshogbo	if (!nvlist_exists_number(nvlin, "size"))
100296047Soshogbo		return (EINVAL);
101296047Soshogbo
102296047Soshogbo	size = (size_t)nvlist_get_number(nvlin, "size");
103296047Soshogbo	if (size == 0 || size > MAXSIZE)
104296047Soshogbo		return (EINVAL);
105296047Soshogbo
106296047Soshogbo	data = malloc(size);
107296047Soshogbo	if (data == NULL)
108296047Soshogbo		return (ENOMEM);
109296047Soshogbo
110296047Soshogbo	arc4random_buf(data, size);
111296047Soshogbo
112296047Soshogbo	nvlist_move_binary(nvlout, "data", data, size);
113296047Soshogbo
114296047Soshogbo	return (0);
115296047Soshogbo}
116296047Soshogbo
117301572SoshogboCREATE_SERVICE("system.random", NULL, random_command, 0);
118