1 | /* |
2 | * ccmode_siv.h |
3 | * corecrypto |
4 | * |
5 | * Created on 11/13/2015 |
6 | * |
7 | * Copyright (c) 2015 Apple Inc. All rights reserved. |
8 | * |
9 | */ |
10 | |
11 | #ifndef _CORECRYPTO_CCMODE_SIV_H_ |
12 | #define _CORECRYPTO_CCMODE_SIV_H_ |
13 | |
14 | #include <corecrypto/cc.h> |
15 | #include <corecrypto/ccmode.h> |
16 | #include <corecrypto/ccmode_impl.h> |
17 | |
18 | #include <corecrypto/cccmac.h> |
19 | |
20 | /* This provide an implementation of SIV |
21 | as specified in https://tools.ietf.org/html/rfc5297 |
22 | also in http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/siv/siv.pdf |
23 | Counter Mode where IV is based on CMAC |
24 | */ |
25 | |
26 | cc_aligned_struct(16) ccsiv_ctx; |
27 | |
28 | struct ccmode_siv { |
29 | size_t size; /* first argument to ccsiv_ctx_decl(). */ |
30 | size_t block_size; |
31 | int (*init)(const struct ccmode_siv *siv, ccsiv_ctx *ctx, |
32 | size_t key_len, const uint8_t *key); |
33 | int (*set_nonce)(ccsiv_ctx *ctx, size_t nbytes, const uint8_t *in); // could just be ccm with NULL out |
34 | int (*auth)(ccsiv_ctx *ctx, size_t nbytes, const uint8_t *in); // could just be ccm with NULL out |
35 | int (*crypt)(ccsiv_ctx *ctx, size_t nbytes, const uint8_t *in, uint8_t *out); |
36 | int (*reset)(ccsiv_ctx *ctx); |
37 | const struct ccmode_cbc *cbc; |
38 | const struct ccmode_ctr *ctr; |
39 | }; |
40 | |
41 | #define ccsiv_ctx_decl(_size_, _name_) cc_ctx_decl(ccsiv_ctx, _size_, _name_) |
42 | #define ccsiv_ctx_clear(_size_, _name_) cc_clear(_size_, _name_) |
43 | |
44 | // Functions |
45 | |
46 | CC_INLINE size_t ccsiv_context_size(const struct ccmode_siv *mode) |
47 | { |
48 | return mode->size; |
49 | } |
50 | |
51 | CC_INLINE size_t ccsiv_block_size(const struct ccmode_siv *mode) |
52 | { |
53 | return mode->block_size; |
54 | } |
55 | |
56 | CC_INLINE size_t ccsiv_ciphertext_size(const struct ccmode_siv *mode, |
57 | size_t plaintext_size) |
58 | { |
59 | return plaintext_size+mode->cbc->block_size; |
60 | } |
61 | |
62 | CC_INLINE size_t ccsiv_plaintext_size(const struct ccmode_siv *mode, |
63 | size_t ciphertext_size) |
64 | { |
65 | if (ciphertext_size<mode->cbc->block_size) { |
66 | return 0; // error |
67 | } |
68 | return ciphertext_size-mode->cbc->block_size; |
69 | } |
70 | |
71 | // Supported key sizes are 32, 48, 64 bytes |
72 | CC_INLINE int ccsiv_init(const struct ccmode_siv *mode, ccsiv_ctx *ctx, |
73 | size_t key_byte_len, const uint8_t *key) |
74 | { |
75 | return mode->init(mode, ctx, key_byte_len, key); |
76 | } |
77 | |
78 | // Process nonce. it is actually just an authenticated data |
79 | CC_INLINE int ccsiv_set_nonce(const struct ccmode_siv *mode, ccsiv_ctx *ctx, |
80 | size_t nbytes, const uint8_t *in) |
81 | { |
82 | return mode->set_nonce(ctx, nbytes, in); |
83 | } |
84 | |
85 | // Process authenticated data. Taken into account for authentication but not |
86 | // encrypted |
87 | CC_INLINE int ccsiv_aad(const struct ccmode_siv *mode, ccsiv_ctx *ctx, |
88 | size_t nbytes, const uint8_t *in) |
89 | { |
90 | return mode->auth(ctx, nbytes, in); |
91 | } |
92 | |
93 | // Encryption data. Authenticated and encrypted. |
94 | // Encrypt/Decrypt can only be called once |
95 | CC_INLINE int ccsiv_crypt(const struct ccmode_siv *mode, ccsiv_ctx *ctx, |
96 | size_t nbytes, const uint8_t *in, uint8_t *out) |
97 | { |
98 | return mode->crypt(ctx, nbytes, in, out); |
99 | } |
100 | |
101 | // Clear all context for reuse. |
102 | // Key is clear to avoid leaking it |
103 | CC_INLINE int ccsiv_reset(const struct ccmode_siv *mode, ccsiv_ctx *ctx) |
104 | { |
105 | return mode->reset(ctx); |
106 | } |
107 | |
108 | // One shot with only one vector of adata |
109 | CC_INLINE int ccsiv_one_shot(const struct ccmode_siv *mode, |
110 | size_t key_len, const uint8_t *key, |
111 | unsigned nonce_nbytes, const uint8_t* nonce, |
112 | unsigned adata_nbytes, const uint8_t* adata, |
113 | size_t in_nbytes, const uint8_t *in, uint8_t *out) |
114 | { |
115 | int rc; |
116 | ccsiv_ctx_decl(mode->size, ctx); |
117 | rc=mode->init(mode, ctx, key_len, key); |
118 | if (rc) {return rc;} |
119 | rc=mode->set_nonce(ctx, nonce_nbytes, nonce); |
120 | if (rc) {return rc;} |
121 | rc=mode->auth(ctx, adata_nbytes, adata); |
122 | if (rc) {return rc;} |
123 | rc=mode->crypt(ctx, in_nbytes, in, out); |
124 | if (rc) {return rc;} |
125 | ccsiv_ctx_clear(mode->size, ctx); |
126 | return rc; |
127 | } |
128 | |
129 | #endif /* _CORECRYPTO_CCMODE_H_ */ |
130 | |