1: /*
2: * Copyright (C) 2013 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include "iv_gen_seq.h"
17:
18: /**
19: * Magic value for the initial IV state
20: */
21: #define SEQ_IV_INIT_STATE (~(uint64_t)0)
22: #define SEQ_IV_HIGH_MASK (1ULL << 63)
23:
24: typedef struct private_iv_gen_t private_iv_gen_t;
25:
26: /**
27: * Private data of an iv_gen_t object.
28: */
29: struct private_iv_gen_t {
30:
31: /**
32: * Public iv_gen_t interface.
33: */
34: iv_gen_t public;
35:
36: /**
37: * Previously passed sequence number in lower space to enforce uniqueness
38: */
39: uint64_t prevl;
40:
41: /**
42: * Previously passed sequence number in upper space to enforce uniqueness
43: */
44: uint64_t prevh;
45:
46: /**
47: * Salt to mask counter
48: */
49: uint8_t *salt;
50: };
51:
52: METHOD(iv_gen_t, get_iv, bool,
53: private_iv_gen_t *this, uint64_t seq, size_t size, uint8_t *buffer)
54: {
55: uint8_t iv[sizeof(uint64_t)];
56: size_t len = size;
57:
58: if (!this->salt)
59: {
60: return FALSE;
61: }
62: if (size < sizeof(uint64_t))
63: {
64: return FALSE;
65: }
66: if (this->prevl != SEQ_IV_INIT_STATE && seq <= this->prevl)
67: {
68: seq |= SEQ_IV_HIGH_MASK;
69: if (this->prevh != SEQ_IV_INIT_STATE && seq <= this->prevh)
70: {
71: return FALSE;
72: }
73: }
74: if ((seq | SEQ_IV_HIGH_MASK) == SEQ_IV_INIT_STATE)
75: {
76: return FALSE;
77: }
78: if (seq & SEQ_IV_HIGH_MASK)
79: {
80: this->prevh = seq;
81: }
82: else
83: {
84: this->prevl = seq;
85: }
86: if (len > sizeof(uint64_t))
87: {
88: len = sizeof(uint64_t);
89: memset(buffer, 0, size - len);
90: }
91: htoun64(iv, seq);
92: memxor(iv, this->salt, sizeof(uint64_t));
93: memcpy(buffer + size - len, iv + sizeof(uint64_t) - len, len);
94: return TRUE;
95: }
96:
97: METHOD(iv_gen_t, allocate_iv, bool,
98: private_iv_gen_t *this, uint64_t seq, size_t size, chunk_t *chunk)
99: {
100: *chunk = chunk_alloc(size);
101: if (!get_iv(this, seq, chunk->len, chunk->ptr))
102: {
103: chunk_free(chunk);
104: return FALSE;
105: }
106: return TRUE;
107: }
108:
109: METHOD(iv_gen_t, destroy, void,
110: private_iv_gen_t *this)
111: {
112: free(this->salt);
113: free(this);
114: }
115:
116: iv_gen_t *iv_gen_seq_create()
117: {
118: private_iv_gen_t *this;
119: rng_t *rng;
120:
121: INIT(this,
122: .public = {
123: .get_iv = _get_iv,
124: .allocate_iv = _allocate_iv,
125: .destroy = _destroy,
126: },
127: .prevl = SEQ_IV_INIT_STATE,
128: .prevh = SEQ_IV_INIT_STATE,
129: );
130:
131: rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
132: if (rng)
133: {
134: this->salt = malloc(sizeof(uint64_t));
135: if (!rng->get_bytes(rng, sizeof(uint64_t), this->salt))
136: {
137: free(this->salt);
138: this->salt = NULL;
139: }
140: rng->destroy(rng);
141: }
142:
143: return &this->public;
144: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>