/src/libgcrypt/cipher/cipher-ctr.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* cipher-ctr.c - Generic CTR mode implementation |
2 | | * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 |
3 | | * 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc. |
4 | | * |
5 | | * This file is part of Libgcrypt. |
6 | | * |
7 | | * Libgcrypt is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU Lesser general Public License as |
9 | | * published by the Free Software Foundation; either version 2.1 of |
10 | | * the License, or (at your option) any later version. |
11 | | * |
12 | | * Libgcrypt is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with this program; if not, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #include <config.h> |
22 | | #include <stdio.h> |
23 | | #include <stdlib.h> |
24 | | #include <string.h> |
25 | | #include <errno.h> |
26 | | |
27 | | #include "g10lib.h" |
28 | | #include "cipher.h" |
29 | | #include "bufhelp.h" |
30 | | #include "./cipher-internal.h" |
31 | | |
32 | | |
33 | | gcry_err_code_t |
34 | | _gcry_cipher_ctr_encrypt_ctx (gcry_cipher_hd_t c, |
35 | | unsigned char *outbuf, size_t outbuflen, |
36 | | const unsigned char *inbuf, size_t inbuflen, |
37 | | void *algo_context) |
38 | 0 | { |
39 | 0 | size_t n; |
40 | 0 | int i; |
41 | 0 | gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; |
42 | 0 | size_t blocksize_shift = _gcry_blocksize_shift(c); |
43 | 0 | size_t blocksize = 1 << blocksize_shift; |
44 | 0 | size_t nblocks; |
45 | 0 | unsigned int burn, nburn; |
46 | |
|
47 | 0 | if (outbuflen < inbuflen) |
48 | 0 | return GPG_ERR_BUFFER_TOO_SHORT; |
49 | | |
50 | 0 | burn = 0; |
51 | | |
52 | | /* First process a left over encrypted counter. */ |
53 | 0 | if (c->unused) |
54 | 0 | { |
55 | 0 | gcry_assert (c->unused < blocksize); |
56 | 0 | i = blocksize - c->unused; |
57 | 0 | n = c->unused > inbuflen ? inbuflen : c->unused; |
58 | 0 | buf_xor(outbuf, inbuf, &c->lastiv[i], n); |
59 | 0 | c->unused -= n; |
60 | 0 | inbuf += n; |
61 | 0 | outbuf += n; |
62 | 0 | inbuflen -= n; |
63 | 0 | } |
64 | | |
65 | | /* Use a bulk method if available. */ |
66 | 0 | nblocks = inbuflen >> blocksize_shift; |
67 | 0 | if (nblocks && c->bulk.ctr_enc) |
68 | 0 | { |
69 | 0 | c->bulk.ctr_enc (algo_context, c->u_ctr.ctr, outbuf, inbuf, nblocks); |
70 | 0 | inbuf += nblocks << blocksize_shift; |
71 | 0 | outbuf += nblocks << blocksize_shift; |
72 | 0 | inbuflen -= nblocks << blocksize_shift; |
73 | 0 | } |
74 | | |
75 | | /* If we don't have a bulk method use the standard method. We also |
76 | | use this method for the a remaining partial block. */ |
77 | 0 | if (inbuflen) |
78 | 0 | { |
79 | 0 | unsigned char tmp[MAX_BLOCKSIZE]; |
80 | |
|
81 | 0 | n = blocksize; |
82 | 0 | do |
83 | 0 | { |
84 | 0 | nburn = enc_fn (algo_context, tmp, c->u_ctr.ctr); |
85 | 0 | burn = nburn > burn ? nburn : burn; |
86 | |
|
87 | 0 | cipher_block_add(c->u_ctr.ctr, 1, blocksize); |
88 | |
|
89 | 0 | if (inbuflen < blocksize) |
90 | 0 | break; |
91 | 0 | cipher_block_xor(outbuf, inbuf, tmp, blocksize); |
92 | |
|
93 | 0 | inbuflen -= n; |
94 | 0 | outbuf += n; |
95 | 0 | inbuf += n; |
96 | 0 | } |
97 | 0 | while (inbuflen); |
98 | | |
99 | 0 | if (inbuflen) |
100 | 0 | { |
101 | 0 | n = inbuflen; |
102 | 0 | buf_xor(outbuf, inbuf, tmp, inbuflen); |
103 | |
|
104 | 0 | inbuflen -= n; |
105 | 0 | outbuf += n; |
106 | 0 | inbuf += n; |
107 | 0 | } |
108 | | |
109 | | /* Save the unused bytes of the counter. */ |
110 | 0 | c->unused = blocksize - n; |
111 | 0 | if (c->unused) |
112 | 0 | buf_cpy (c->lastiv+n, tmp+n, c->unused); |
113 | |
|
114 | 0 | wipememory (tmp, sizeof tmp); |
115 | 0 | } |
116 | | |
117 | 0 | if (burn > 0) |
118 | 0 | _gcry_burn_stack (burn + 4 * sizeof(void *)); |
119 | |
|
120 | 0 | return 0; |
121 | 0 | } |
122 | | |
123 | | |
124 | | gcry_err_code_t |
125 | | _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c, |
126 | | unsigned char *outbuf, size_t outbuflen, |
127 | | const unsigned char *inbuf, size_t inbuflen) |
128 | 0 | { |
129 | 0 | return _gcry_cipher_ctr_encrypt_ctx (c, outbuf, outbuflen, inbuf, inbuflen, |
130 | 0 | &c->context.c); |
131 | 0 | } |