source: trunk/src-cryptopp/asn.cpp

Last change on this file was e230cb0, checked in by David Stainton <dstainton415@…>, at 2016-10-12T13:27:29Z

Add cryptopp from tag CRYPTOPP_5_6_5

  • Property mode set to 100644
File size: 13.9 KB
Line 
1// asn.cpp - written and placed in the public domain by Wei Dai
2
3#include "pch.h"
4#include "config.h"
5
6#ifndef CRYPTOPP_IMPORTS
7
8#include "asn.h"
9
10#include <iomanip>
11#include <time.h>
12
13NAMESPACE_BEGIN(CryptoPP)
14USING_NAMESPACE(std)
15
16/// DER Length
17size_t DERLengthEncode(BufferedTransformation &bt, lword length)
18{
19        size_t i=0;
20        if (length <= 0x7f)
21        {
22                bt.Put(byte(length));
23                i++;
24        }
25        else
26        {
27                bt.Put(byte(BytePrecision(length) | 0x80));
28                i++;
29                for (int j=BytePrecision(length); j; --j)
30                {
31                        bt.Put(byte(length >> (j-1)*8));
32                        i++;
33                }
34        }
35        return i;
36}
37
38bool BERLengthDecode(BufferedTransformation &bt, lword &length, bool &definiteLength)
39{
40        byte b;
41
42        if (!bt.Get(b))
43                return false;
44
45        if (!(b & 0x80))
46        {
47                definiteLength = true;
48                length = b;
49        }
50        else
51        {
52                unsigned int lengthBytes = b & 0x7f;
53
54                if (lengthBytes == 0)
55                {
56                        definiteLength = false;
57                        return true;
58                }
59
60                definiteLength = true;
61                length = 0;
62                while (lengthBytes--)
63                {
64                        if (length >> (8*(sizeof(length)-1)))
65                                BERDecodeError();       // length about to overflow
66
67                        if (!bt.Get(b))
68                                return false;
69
70                        length = (length << 8) | b;
71                }
72        }
73        return true;
74}
75
76bool BERLengthDecode(BufferedTransformation &bt, size_t &length)
77{
78        lword lw = 0;
79        bool definiteLength;
80        if (!BERLengthDecode(bt, lw, definiteLength))
81                BERDecodeError();
82        if (!SafeConvert(lw, length))
83                BERDecodeError();
84        return definiteLength;
85}
86
87void DEREncodeNull(BufferedTransformation &out)
88{
89        out.Put(TAG_NULL);
90        out.Put(0);
91}
92
93void BERDecodeNull(BufferedTransformation &in)
94{
95        byte b;
96        if (!in.Get(b) || b != TAG_NULL)
97                BERDecodeError();
98        size_t length;
99        if (!BERLengthDecode(in, length) || length != 0)
100                BERDecodeError();
101}
102
103/// ASN Strings
104size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen)
105{
106        bt.Put(OCTET_STRING);
107        size_t lengthBytes = DERLengthEncode(bt, strLen);
108        bt.Put(str, strLen);
109        return 1+lengthBytes+strLen;
110}
111
112size_t DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str)
113{
114        return DEREncodeOctetString(bt, str.begin(), str.size());
115}
116
117size_t BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str)
118{
119        byte b;
120        if (!bt.Get(b) || b != OCTET_STRING)
121                BERDecodeError();
122
123        size_t bc;
124        if (!BERLengthDecode(bt, bc))
125                BERDecodeError();
126
127        str.New(bc);
128        if (bc != bt.Get(str, bc))
129                BERDecodeError();
130        return bc;
131}
132
133size_t BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str)
134{
135        byte b;
136        if (!bt.Get(b) || b != OCTET_STRING)
137                BERDecodeError();
138
139        size_t bc;
140        if (!BERLengthDecode(bt, bc))
141                BERDecodeError();
142
143        bt.TransferTo(str, bc);
144        return bc;
145}
146
147size_t DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag)
148{
149        bt.Put(asnTag);
150        size_t lengthBytes = DERLengthEncode(bt, str.size());
151        bt.Put((const byte *)str.data(), str.size());
152        return 1+lengthBytes+str.size();
153}
154
155size_t BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag)
156{
157        byte b;
158        if (!bt.Get(b) || b != asnTag)
159                BERDecodeError();
160
161        size_t bc;
162        if (!BERLengthDecode(bt, bc))
163                BERDecodeError();
164
165        SecByteBlock temp(bc);
166        if (bc != bt.Get(temp, bc))
167                BERDecodeError();
168        str.assign((char *)temp.begin(), bc);
169        return bc;
170}
171
172/// ASN BitString
173size_t DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits)
174{
175        bt.Put(BIT_STRING);
176        size_t lengthBytes = DERLengthEncode(bt, strLen+1);
177        bt.Put((byte)unusedBits);
178        bt.Put(str, strLen);
179        return 2+lengthBytes+strLen;
180}
181
182size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits)
183{
184        byte b;
185        if (!bt.Get(b) || b != BIT_STRING)
186                BERDecodeError();
187
188        size_t bc;
189        if (!BERLengthDecode(bt, bc))
190                BERDecodeError();
191
192        byte unused;
193        if (!bt.Get(unused))
194                BERDecodeError();
195        unusedBits = unused;
196        str.resize(bc-1);
197        if ((bc-1) != bt.Get(str, bc-1))
198                BERDecodeError();
199        return bc-1;
200}
201
202void DERReencode(BufferedTransformation &source, BufferedTransformation &dest)
203{
204        byte tag;
205        source.Peek(tag);
206        BERGeneralDecoder decoder(source, tag);
207        DERGeneralEncoder encoder(dest, tag);
208        if (decoder.IsDefiniteLength())
209                decoder.TransferTo(encoder, decoder.RemainingLength());
210        else
211        {
212                while (!decoder.EndReached())
213                        DERReencode(decoder, encoder);
214        }
215        decoder.MessageEnd();
216        encoder.MessageEnd();
217}
218
219void OID::EncodeValue(BufferedTransformation &bt, word32 v)
220{
221        for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7)
222                bt.Put((byte)(0x80 | ((v >> i) & 0x7f)));
223        bt.Put((byte)(v & 0x7f));
224}
225
226size_t OID::DecodeValue(BufferedTransformation &bt, word32 &v)
227{
228        byte b;
229        size_t i=0;
230        v = 0;
231        while (true)
232        {
233                if (!bt.Get(b))
234                        BERDecodeError();
235                i++;
236                if (v >> (8*sizeof(v)-7))       // v about to overflow
237                        BERDecodeError();
238                v <<= 7;
239                v += b & 0x7f;
240                if (!(b & 0x80))
241                        return i;
242        }
243}
244
245void OID::DEREncode(BufferedTransformation &bt) const
246{
247        CRYPTOPP_ASSERT(m_values.size() >= 2);
248        ByteQueue temp;
249        temp.Put(byte(m_values[0] * 40 + m_values[1]));
250        for (size_t i=2; i<m_values.size(); i++)
251                EncodeValue(temp, m_values[i]);
252        bt.Put(OBJECT_IDENTIFIER);
253        DERLengthEncode(bt, temp.CurrentSize());
254        temp.TransferTo(bt);
255}
256
257void OID::BERDecode(BufferedTransformation &bt)
258{
259        byte b;
260        if (!bt.Get(b) || b != OBJECT_IDENTIFIER)
261                BERDecodeError();
262
263        size_t length;
264        if (!BERLengthDecode(bt, length) || length < 1)
265                BERDecodeError();
266
267        if (!bt.Get(b))
268                BERDecodeError();
269
270        length--;
271        m_values.resize(2);
272        m_values[0] = b / 40;
273        m_values[1] = b % 40;
274
275        while (length > 0)
276        {
277                word32 v;
278                size_t valueLen = DecodeValue(bt, v);
279                if (valueLen > length)
280                        BERDecodeError();
281                m_values.push_back(v);
282                length -= valueLen;
283        }
284}
285
286void OID::BERDecodeAndCheck(BufferedTransformation &bt) const
287{
288        OID oid(bt);
289        if (*this != oid)
290                BERDecodeError();
291}
292
293inline BufferedTransformation & EncodedObjectFilter::CurrentTarget()
294{
295        if (m_flags & PUT_OBJECTS)
296                return *AttachedTransformation();
297        else
298                return TheBitBucket();
299}
300
301void EncodedObjectFilter::Put(const byte *inString, size_t length)
302{
303        if (m_nCurrentObject == m_nObjects)
304        {
305                AttachedTransformation()->Put(inString, length);
306                return;
307        }
308
309        LazyPutter lazyPutter(m_queue, inString, length);
310
311        while (m_queue.AnyRetrievable())
312        {
313                switch (m_state)
314                {
315                case IDENTIFIER:
316                        if (!m_queue.Get(m_id))
317                                return;
318                        m_queue.TransferTo(CurrentTarget(), 1);
319                        m_state = LENGTH;       // fall through
320                case LENGTH:
321                {
322                        byte b;
323                        if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0)
324                        {
325                                m_queue.TransferTo(CurrentTarget(), 1);
326                                m_level--;
327                                m_state = IDENTIFIER;
328                                break;
329                        }
330                        ByteQueue::Walker walker(m_queue);
331                        bool definiteLength;
332                        if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength))
333                                return;
334                        m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition());
335                        if (!((m_id & CONSTRUCTED) || definiteLength))
336                                BERDecodeError();
337                        if (!definiteLength)
338                        {
339                                if (!(m_id & CONSTRUCTED))
340                                        BERDecodeError();
341                                m_level++;
342                                m_state = IDENTIFIER;
343                                break;
344                        }
345                        m_state = BODY;         // fall through
346                }
347                case BODY:
348                        m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining);
349
350                        if (m_lengthRemaining == 0)
351                                m_state = IDENTIFIER;
352
353                case TAIL:                      // silence warnings
354                case ALL_DONE:
355                default: ;;
356                }
357
358                if (m_state == IDENTIFIER && m_level == 0)
359                {
360                        // just finished processing a level 0 object
361                        ++m_nCurrentObject;
362
363                        if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT)
364                                AttachedTransformation()->MessageEnd();
365
366                        if (m_nCurrentObject == m_nObjects)
367                        {
368                                if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS)
369                                        AttachedTransformation()->MessageEnd();
370
371                                if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS)
372                                        AttachedTransformation()->MessageSeriesEnd();
373
374                                m_queue.TransferAllTo(*AttachedTransformation());
375                                return;
376                        }
377                }
378        }
379}
380
381BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag)
382        : m_inQueue(inQueue), m_finished(false)
383{
384        Init(asnTag);
385}
386
387BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag)
388        : m_inQueue(inQueue), m_finished(false)
389{
390        Init(asnTag);
391}
392
393void BERGeneralDecoder::Init(byte asnTag)
394{
395        byte b;
396        if (!m_inQueue.Get(b) || b != asnTag)
397                BERDecodeError();
398
399        if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength))
400                BERDecodeError();
401
402        if (!m_definiteLength && !(asnTag & CONSTRUCTED))
403                BERDecodeError();       // cannot be primitive and have indefinite length
404}
405
406BERGeneralDecoder::~BERGeneralDecoder()
407{
408        try     // avoid throwing in destructor
409        {
410                if (!m_finished)
411                        MessageEnd();
412        }
413        catch (const Exception&)
414        {
415                // CRYPTOPP_ASSERT(0);
416        }
417}
418
419bool BERGeneralDecoder::EndReached() const
420{
421        if (m_definiteLength)
422                return m_length == 0;
423        else
424        {       // check end-of-content octets
425                word16 i;
426                return (m_inQueue.PeekWord16(i)==2 && i==0);
427        }
428}
429
430byte BERGeneralDecoder::PeekByte() const
431{
432        byte b;
433        if (!Peek(b))
434                BERDecodeError();
435        return b;
436}
437
438void BERGeneralDecoder::CheckByte(byte check)
439{
440        byte b;
441        if (!Get(b) || b != check)
442                BERDecodeError();
443}
444
445void BERGeneralDecoder::MessageEnd()
446{
447        m_finished = true;
448        if (m_definiteLength)
449        {
450                if (m_length != 0)
451                        BERDecodeError();
452        }
453        else
454        {       // remove end-of-content octets
455                word16 i;
456                if (m_inQueue.GetWord16(i) != 2 || i != 0)
457                        BERDecodeError();
458        }
459}
460
461size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
462{
463        if (m_definiteLength && transferBytes > m_length)
464                transferBytes = m_length;
465        size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking);
466        ReduceLength(transferBytes);
467        return blockedBytes;
468}
469
470size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
471{
472        if (m_definiteLength)
473                end = STDMIN(m_length, end);
474        return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking);
475}
476
477lword BERGeneralDecoder::ReduceLength(lword delta)
478{
479        if (m_definiteLength)
480        {
481                if (m_length < delta)
482                        BERDecodeError();
483                m_length -= delta;
484        }
485        return delta;
486}
487
488DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag)
489        : ByteQueue(), m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
490{
491}
492
493// TODO: GCC (and likely other compilers) identify this as a copy constructor; and not a constructor.
494//   We have to wait until Crypto++ 6.0 to fix it becuase the signature change breaks versioning.
495DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag)
496        : ByteQueue(), m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
497{
498}
499
500DERGeneralEncoder::~DERGeneralEncoder()
501{
502        try     // avoid throwing in constructor
503        {
504                if (!m_finished)
505                        MessageEnd();
506        }
507        catch (const Exception&)
508        {
509                CRYPTOPP_ASSERT(0);
510        }
511}
512
513void DERGeneralEncoder::MessageEnd()
514{
515        m_finished = true;
516        lword length = CurrentSize();
517        m_outQueue.Put(m_asnTag);
518        DERLengthEncode(m_outQueue, length);
519        TransferTo(m_outQueue);
520}
521
522// *************************************************************
523
524void X509PublicKey::BERDecode(BufferedTransformation &bt)
525{
526        BERSequenceDecoder subjectPublicKeyInfo(bt);
527                BERSequenceDecoder algorithm(subjectPublicKeyInfo);
528                        GetAlgorithmID().BERDecodeAndCheck(algorithm);
529                        bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
530                algorithm.MessageEnd();
531
532                BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
533                        subjectPublicKey.CheckByte(0);  // unused bits
534                        BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength());
535                subjectPublicKey.MessageEnd();
536        subjectPublicKeyInfo.MessageEnd();
537}
538
539void X509PublicKey::DEREncode(BufferedTransformation &bt) const
540{
541        DERSequenceEncoder subjectPublicKeyInfo(bt);
542
543                DERSequenceEncoder algorithm(subjectPublicKeyInfo);
544                        GetAlgorithmID().DEREncode(algorithm);
545                        DEREncodeAlgorithmParameters(algorithm);
546                algorithm.MessageEnd();
547
548                DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
549                        subjectPublicKey.Put(0);        // unused bits
550                        DEREncodePublicKey(subjectPublicKey);
551                subjectPublicKey.MessageEnd();
552
553        subjectPublicKeyInfo.MessageEnd();
554}
555
556void PKCS8PrivateKey::BERDecode(BufferedTransformation &bt)
557{
558        BERSequenceDecoder privateKeyInfo(bt);
559                word32 version;
560                BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0);      // check version
561
562                BERSequenceDecoder algorithm(privateKeyInfo);
563                        GetAlgorithmID().BERDecodeAndCheck(algorithm);
564                        bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
565                algorithm.MessageEnd();
566
567                BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
568                        BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength());
569                octetString.MessageEnd();
570
571                if (!privateKeyInfo.EndReached())
572                        BERDecodeOptionalAttributes(privateKeyInfo);
573        privateKeyInfo.MessageEnd();
574}
575
576void PKCS8PrivateKey::DEREncode(BufferedTransformation &bt) const
577{
578        DERSequenceEncoder privateKeyInfo(bt);
579                DEREncodeUnsigned<word32>(privateKeyInfo, 0);   // version
580
581                DERSequenceEncoder algorithm(privateKeyInfo);
582                        GetAlgorithmID().DEREncode(algorithm);
583                        DEREncodeAlgorithmParameters(algorithm);
584                algorithm.MessageEnd();
585
586                DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);
587                        DEREncodePrivateKey(octetString);
588                octetString.MessageEnd();
589
590                DEREncodeOptionalAttributes(privateKeyInfo);
591        privateKeyInfo.MessageEnd();
592}
593
594void PKCS8PrivateKey::BERDecodeOptionalAttributes(BufferedTransformation &bt)
595{
596        DERReencode(bt, m_optionalAttributes);
597}
598
599void PKCS8PrivateKey::DEREncodeOptionalAttributes(BufferedTransformation &bt) const
600{
601        m_optionalAttributes.CopyTo(bt);
602}
603
604NAMESPACE_END
605
606#endif
Note: See TracBrowser for help on using the repository browser.