~zooko/cryptopp/trunk

« back to all changes in this revision

Viewing changes to authenc.cpp

  • Committer: weidai
  • Date: 2010-06-18 01:52:34 UTC
  • Revision ID: svn-v4:57ff6487-cd31-0410-9ec3-f628ee90f5f0:trunk/c5:485
avoid SecBlock of arrays

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// authenc.cpp - written and placed in the public domain by Wei Dai
 
2
 
 
3
#include "pch.h"
 
4
 
 
5
#ifndef CRYPTOPP_IMPORTS
 
6
 
 
7
#include "authenc.h"
 
8
 
 
9
NAMESPACE_BEGIN(CryptoPP)
 
10
 
 
11
void AuthenticatedSymmetricCipherBase::AuthenticateData(const byte *input, size_t len)
 
12
{
 
13
        unsigned int blockSize = AuthenticationBlockSize();
 
14
        unsigned int &num = m_bufferedDataLength;
 
15
        byte* data = m_buffer.begin();
 
16
 
 
17
        if (num != 0)   // process left over data
 
18
        {
 
19
                if (num+len >= blockSize)
 
20
                {
 
21
                        memcpy(data+num, input, blockSize-num);
 
22
                        AuthenticateBlocks(data, blockSize);
 
23
                        input += (blockSize-num);
 
24
                        len -= (blockSize-num);
 
25
                        num = 0;
 
26
                        // drop through and do the rest
 
27
                }
 
28
                else
 
29
                {
 
30
                        memcpy(data+num, input, len);
 
31
                        num += (unsigned int)len;
 
32
                        return;
 
33
                }
 
34
        }
 
35
 
 
36
        // now process the input data in blocks of blockSize bytes and save the leftovers to m_data
 
37
        if (len >= blockSize)
 
38
        {
 
39
                size_t leftOver = AuthenticateBlocks(input, len);
 
40
                input += (len - leftOver);
 
41
                len = leftOver;
 
42
        }
 
43
 
 
44
        memcpy(data, input, len);
 
45
        num = (unsigned int)len;
 
46
}
 
47
 
 
48
void AuthenticatedSymmetricCipherBase::SetKey(const byte *userKey, size_t keylength, const NameValuePairs &params)
 
49
{
 
50
        m_bufferedDataLength = 0;
 
51
        m_state = State_Start;
 
52
 
 
53
        SetKeyWithoutResync(userKey, keylength, params);
 
54
        m_state = State_KeySet;
 
55
 
 
56
        size_t length;
 
57
        const byte *iv = GetIVAndThrowIfInvalid(params, length);
 
58
        if (iv)
 
59
                Resynchronize(iv, (int)length);
 
60
}
 
61
 
 
62
void AuthenticatedSymmetricCipherBase::Resynchronize(const byte *iv, int length)
 
63
{
 
64
        if (m_state < State_KeySet)
 
65
                throw BadState(AlgorithmName(), "Resynchronize", "key is set");
 
66
 
 
67
        m_bufferedDataLength = 0;
 
68
        m_totalHeaderLength = m_totalMessageLength = m_totalFooterLength = 0;
 
69
        m_state = State_KeySet;
 
70
 
 
71
        Resync(iv, this->ThrowIfInvalidIVLength(length));
 
72
        m_state = State_IVSet;
 
73
}
 
74
 
 
75
void AuthenticatedSymmetricCipherBase::Update(const byte *input, size_t length)
 
76
{
 
77
        if (length == 0)
 
78
                return;
 
79
 
 
80
        switch (m_state)
 
81
        {
 
82
        case State_Start:
 
83
        case State_KeySet:
 
84
                throw BadState(AlgorithmName(), "Update", "setting key and IV");
 
85
        case State_IVSet:
 
86
                AuthenticateData(input, length);
 
87
                m_totalHeaderLength += length;
 
88
                break;
 
89
        case State_AuthUntransformed:
 
90
        case State_AuthTransformed:
 
91
                AuthenticateLastConfidentialBlock();
 
92
                m_bufferedDataLength = 0;
 
93
                m_state = State_AuthFooter;
 
94
                // fall through
 
95
        case State_AuthFooter:
 
96
                AuthenticateData(input, length);
 
97
                m_totalFooterLength += length;
 
98
                break;
 
99
        default:
 
100
                assert(false);
 
101
        }
 
102
}
 
103
 
 
104
void AuthenticatedSymmetricCipherBase::ProcessData(byte *outString, const byte *inString, size_t length)
 
105
{
 
106
        m_totalMessageLength += length;
 
107
        if (m_state >= State_IVSet && m_totalMessageLength > MaxMessageLength())
 
108
                throw InvalidArgument(AlgorithmName() + ": message length exceeds maximum");
 
109
 
 
110
reswitch:
 
111
        switch (m_state)
 
112
        {
 
113
        case State_Start:
 
114
        case State_KeySet:
 
115
                throw BadState(AlgorithmName(), "ProcessData", "setting key and IV");
 
116
        case State_AuthFooter:
 
117
                throw BadState(AlgorithmName(), "ProcessData was called after footer input has started");
 
118
        case State_IVSet:
 
119
                AuthenticateLastHeaderBlock();
 
120
                m_bufferedDataLength = 0;
 
121
                m_state = AuthenticationIsOnPlaintext()==IsForwardTransformation() ? State_AuthUntransformed : State_AuthTransformed;
 
122
                goto reswitch;
 
123
        case State_AuthUntransformed:
 
124
                AuthenticateData(inString, length);
 
125
                AccessSymmetricCipher().ProcessData(outString, inString, length);
 
126
                break;
 
127
        case State_AuthTransformed:
 
128
                AccessSymmetricCipher().ProcessData(outString, inString, length);
 
129
                AuthenticateData(outString, length);
 
130
                break;
 
131
        default:
 
132
                assert(false);
 
133
        }
 
134
}
 
135
 
 
136
void AuthenticatedSymmetricCipherBase::TruncatedFinal(byte *mac, size_t macSize)
 
137
{
 
138
        if (m_totalHeaderLength > MaxHeaderLength())
 
139
                throw InvalidArgument(AlgorithmName() + ": header length of " + IntToString(m_totalHeaderLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength()));
 
140
 
 
141
        if (m_totalFooterLength > MaxFooterLength())
 
142
        {
 
143
                if (MaxFooterLength() == 0)
 
144
                        throw InvalidArgument(AlgorithmName() + ": additional authenticated data (AAD) cannot be input after data to be encrypted or decrypted");
 
145
                else
 
146
                        throw InvalidArgument(AlgorithmName() + ": footer length of " + IntToString(m_totalFooterLength) + " exceeds the maximum of " + IntToString(MaxFooterLength()));
 
147
        }
 
148
 
 
149
        switch (m_state)
 
150
        {
 
151
        case State_Start:
 
152
        case State_KeySet:
 
153
                throw BadState(AlgorithmName(), "TruncatedFinal", "setting key and IV");
 
154
 
 
155
        case State_IVSet:
 
156
                AuthenticateLastHeaderBlock();
 
157
                m_bufferedDataLength = 0;
 
158
                // fall through
 
159
 
 
160
        case State_AuthUntransformed:
 
161
        case State_AuthTransformed:
 
162
                AuthenticateLastConfidentialBlock();
 
163
                m_bufferedDataLength = 0;
 
164
                // fall through
 
165
 
 
166
        case State_AuthFooter:
 
167
                AuthenticateLastFooterBlock(mac, macSize);
 
168
                m_bufferedDataLength = 0;
 
169
                break;
 
170
 
 
171
        default:
 
172
                assert(false);
 
173
        }
 
174
 
 
175
        m_state = State_KeySet;
 
176
}
 
177
 
 
178
NAMESPACE_END
 
179
 
 
180
#endif