/src/h2o/lib/common/rand.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2021 Goro Fuji, Fastly, Inc. |
3 | | * |
4 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
5 | | * of this software and associated documentation files (the "Software"), to |
6 | | * deal in the Software without restriction, including without limitation the |
7 | | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
8 | | * sell copies of the Software, and to permit persons to whom the Software is |
9 | | * furnished to do so, subject to the following conditions: |
10 | | * |
11 | | * The above copyright notice and this permission notice shall be included in |
12 | | * all copies or substantial portions of the Software. |
13 | | * |
14 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
17 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
18 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
19 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
20 | | * IN THE SOFTWARE. |
21 | | */ |
22 | | |
23 | | #include <openssl/rand.h> |
24 | | #include <inttypes.h> |
25 | | #include "h2o/rand.h" |
26 | | #include "h2o/string_.h" |
27 | | #include "picotls/openssl.h" |
28 | | |
29 | | #if H2O_DEFINE_RAND |
30 | | int h2o_rand(void) |
31 | 0 | { |
32 | 0 | static __thread struct { |
33 | 0 | unsigned seed; |
34 | 0 | unsigned initialized; |
35 | 0 | } state; |
36 | |
|
37 | 0 | if (!state.initialized) { |
38 | 0 | ptls_openssl_random_bytes(&state.seed, sizeof(state.seed)); |
39 | 0 | state.initialized = 1; |
40 | 0 | } |
41 | |
|
42 | 0 | return rand_r(&state.seed); |
43 | 0 | } |
44 | | #endif |
45 | | |
46 | | static void format_uuid_rfc4122(char *dst, uint8_t *octets, uint8_t version) |
47 | 0 | { |
48 | | // Variant: |
49 | | // > Set the two most significant bits (bits 6 and 7) of the |
50 | | // > clock_seq_hi_and_reserved to zero and one, respectively. |
51 | 0 | octets[8] = (octets[8] & 0x3f) | 0x80; |
52 | | // Version: |
53 | | // > Set the four most significant bits (bits 12 through 15) of the |
54 | | // > time_hi_and_version field to the 4-bit version number from |
55 | | // > Section 4.1.3. |
56 | 0 | octets[6] = (octets[6] & 0x0f) | (version << 4); |
57 | | |
58 | | // String Representation: |
59 | | // > UUID = time-low "-" time-mid "-" |
60 | | // > time-high-and-version "-" |
61 | | // > clock-seq-and-reserved |
62 | | // > clock-seq-low "-" node |
63 | | // See also "4.1.2. Layout and Byte Order" for the layout |
64 | 0 | size_t pos = 0; |
65 | |
|
66 | 0 | #define UUID_ENC_PART(first, last) \ |
67 | 0 | do { \ |
68 | 0 | h2o_hex_encode(&dst[pos], &octets[first], last - first + 1); \ |
69 | 0 | pos += (last - first + 1) * 2; \ |
70 | 0 | } while (0) |
71 | |
|
72 | 0 | UUID_ENC_PART(0, 3); /* time_low */ |
73 | 0 | dst[pos++] = '-'; |
74 | 0 | UUID_ENC_PART(4, 5); /* time_mid */ |
75 | 0 | dst[pos++] = '-'; |
76 | 0 | UUID_ENC_PART(6, 7); /* time_hi_and_version */ |
77 | 0 | dst[pos++] = '-'; |
78 | 0 | UUID_ENC_PART(8, 8); /* clock_seq_hi_and_reserved */ |
79 | 0 | UUID_ENC_PART(9, 9); /* clock_seq_low */ |
80 | 0 | dst[pos++] = '-'; |
81 | 0 | UUID_ENC_PART(10, 15); /* node */ |
82 | |
|
83 | 0 | #undef UUID_ENC_PART |
84 | | |
85 | | /* '\0' is set by h2o_hex_encode() */ |
86 | 0 | } |
87 | | |
88 | | void h2o_generate_uuidv4(char *dst) |
89 | 0 | { |
90 | | // RFC-4122 "A Universally Unique IDentifier (UUID) URN Namespace" |
91 | | // 4.4. Algorithms for Creating a UUID from Truly Random or Pseudo-Random Numbers |
92 | |
|
93 | 0 | uint8_t octets[16]; |
94 | 0 | ptls_openssl_random_bytes((void *)&octets, sizeof(octets)); |
95 | 0 | format_uuid_rfc4122(dst, octets, 4); |
96 | 0 | } |