summaryrefslogtreecommitdiff
path: root/src/irmd/oap/hdr.h
blob: f603b169a2aec80c7ef6917df4b2f90ad752f270 (plain)
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 */