1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
#include <mod/hmac.hxx>
#include <libbutl/openssl.hxx>
using namespace std;
using namespace butl;
string brep::
compute_hmac (const options::openssl_options& o,
const vector<char>& m,
const char* k)
{
try
{
fdpipe errp (fdopen_pipe ()); // stderr pipe.
// To compute an HMAC over stdin with the key <secret>:
//
// openssl mac -digest SHA256 -macopt "key:<secret>" HMAC
//
// Note that here we assume both output and diagnostics will fit into pipe
// buffers and don't poll both with fdselect().
//
openssl os (path ("-"), // Read message from openssl::out.
path ("-"), // Write output to openssl::in.
process::pipe (errp.in.get (), move (errp.out)),
process_env (o.openssl (), o.openssl_envvar ()),
"mac", o.openssl_option (),
"-digest", "SHA256",
"-macopt", string ("key:") + k,
"HMAC");
ifdstream err (move (errp.in));
string h; // The HMAC value.
try
{
// In case of an exception, skip and close input after output.
//
// Note: re-open in/out so that they get automatically closed on
// an exception.
//
ifdstream in (os.in.release (), fdstream_mode::skip);
ofdstream out (os.out.release ());
// Write the message to openssl's input.
//
out.write (m.data (), m.size ());
out.close ();
// Read the HMAC value from openssl's output.
//
h = in.read_text ();
in.close ();
}
catch (const io_error& e)
{
// If the process exits with non-zero status, assume the IO error is due
// to that and fall through.
//
if (os.wait ())
{
throw_generic_error (
e.code ().value (),
(string ("unable to read/write openssl stdout/stdin: ") +
e.what ()).c_str ());
}
}
if (!os.wait ())
{
string et (err.read_text ());
throw_generic_error (EINVAL,
("non-zero openssl exit status: " + et).c_str ());
}
err.close ();
return h;
}
catch (const process_error& e)
{
throw_generic_error (
e.code ().value (),
(string ("unable to execute openssl: ") + e.what ()).c_str ());
}
catch (const io_error& e)
{
// Unable to read diagnostics from stderr.
//
throw_generic_error (
e.code ().value (),
(string ("unable to read openssl stderr : ") + e.what ()).c_str ());
}
}
|