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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
/*
* Ouroboros - Copyright (C) 2016 - 2024
*
* OAP - Header definitions and functions
*
* Dimitri Staessens <dimitri@ouroboros.rocks>
* Sander Vrijders <sander@ouroboros.rocks>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., http://www.fsf.org/about/contact/.
*/
#ifndef OUROBOROS_IRMD_OAP_HDR_H
#define OUROBOROS_IRMD_OAP_HDR_H
#include <ouroboros/crypt.h>
#include <ouroboros/utils.h>
#include <stdbool.h>
#include <stdint.h>
#define OAP_ID_SIZE (16)
#define OAP_HDR_MIN_SIZE (OAP_ID_SIZE + sizeof(uint64_t) + 6 * sizeof(uint16_t))
#define OAP_KEX_FMT_BIT 0x8000 /* bit 15: 0=X.509 DER, 1=Raw */
#define OAP_KEX_ROLE_BIT 0x4000 /* bit 14: 0=Server encaps, 1=Client encaps */
#define OAP_KEX_LEN_MASK 0x3FFF /* bits 0-13: Length (0-16383 bytes) */
#define OAP_KEX_ROLE(hdr) (hdr->kex_flags.role)
#define OAP_KEX_FMT(hdr) (hdr->kex_flags.fmt)
#define OAP_KEX_IS_X509_FMT(hdr) (((hdr)->kex_flags.fmt) == 0)
#define OAP_KEX_IS_RAW_FMT(hdr) (((hdr)->kex_flags.fmt) == 1)
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ---+
* | | |
* + + |
* | | |
* + id (128 bits) + |
* | Unique flow allocation ID | |
* + + |
* | | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
* | | |
* + timestamp (64 bits) + |
* | UTC nanoseconds since epoch | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
* | cipher_nid (16 bits) | kdf_nid (16 bits) | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
* | md_nid (16 bits) | crt_len (16 bits) | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
* |F|R| kex_len (14 bits) | data_len (16 bits) | | Signed
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Region
* | | |
* + certificate (variable) + |
* | X.509 certificate, DER encoded | |
* + + |
* | | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
* | | |
* + kex_data (variable) + |
* | public key (DER/raw) or ciphertext (KEM) | |
* + + |
* | | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
* | | |
* + data (variable) + |
* | Piggybacked application data | |
* + + |
* | | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
* | | |
* + req_hash (variable, response only) + |
* | H(request) using req md_nid / sha384 | |
* | | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ---+
* | |
* + signature (variable) +
* | DSA signature over signed region |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* cipher_nid: NID value for symmetric cipher (0 = none)
* kdf_nid: NID value for KDF function (0 = none)
* md_nid: NID value for signature hash (0 = PQC/no signature)
*
* kex_len field bit layout:
* F (bit 15): Format - 0 = X.509 DER, 1 = Raw/Hybrid
* R (bit 14): Role - 0 = Server encaps, 1 = Client encaps
* (R is ignored for non-KEM algorithms)
* Bits 0-13: Length (0-16383 bytes)
*
* Request: sig_len = total - 36 - crt_len - kex_len - data_len
* Response: sig_len = total - 36 - crt_len - kex_len - data_len - hash_len
* where hash_len = md_len(req_md_nid / sha384)
*/
/* Parsed OAP header - buffers pointing to a single memory region */
struct oap_hdr {
const char * cipher_str;
const char * kdf_str;
const char * md_str;
uint64_t timestamp;
uint16_t nid;
uint16_t kdf_nid;
uint16_t md_nid;
struct {
bool fmt; /* Format */
bool role; /* Role */
} kex_flags;
buffer_t id;
buffer_t crt;
buffer_t kex;
buffer_t data;
buffer_t req_hash; /* H(request) - response only */
buffer_t sig;
buffer_t hdr;
};
void oap_hdr_init(struct oap_hdr * hdr,
buffer_t id,
uint8_t * kex_buf,
buffer_t data,
uint16_t nid);
void oap_hdr_fini(struct oap_hdr * oap_hdr);
int oap_hdr_encode(struct oap_hdr * hdr,
void * pkp,
void * crt,
struct sec_config * kcfg,
buffer_t req_hash,
int req_md_nid);
int oap_hdr_decode(struct oap_hdr * hdr,
buffer_t buf,
int req_md_nid);
void debug_oap_hdr_rcv(const struct oap_hdr * hdr);
void debug_oap_hdr_snd(const struct oap_hdr * hdr);
int oap_hdr_copy_data(const struct oap_hdr * hdr,
buffer_t * out);
#endif /* OUROBOROS_IRMD_OAP_HDR_H */
|