Coverage Report

Created: 2024-11-21 07:03

/src/cryptopp/asn.h
Line
Count
Source (jump to first uncovered line)
1
// asn.h - originally written and placed in the public domain by Wei Dai
2
3
/// \file asn.h
4
/// \brief Classes and functions for working with ANS.1 objects
5
6
#ifndef CRYPTOPP_ASN_H
7
#define CRYPTOPP_ASN_H
8
9
#include "cryptlib.h"
10
#include "filters.h"
11
#include "smartptr.h"
12
#include "stdcpp.h"
13
#include "queue.h"
14
#include "misc.h"
15
16
#include <iosfwd>
17
18
// Issue 340
19
#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
20
# pragma GCC diagnostic push
21
# pragma GCC diagnostic ignored "-Wconversion"
22
# pragma GCC diagnostic ignored "-Wsign-conversion"
23
#endif
24
25
NAMESPACE_BEGIN(CryptoPP)
26
27
/// \brief ASN.1 types
28
/// \note These tags are not complete
29
enum ASNTag
30
{
31
  /// \brief ASN.1 Boolean
32
  BOOLEAN       = 0x01,
33
  /// \brief ASN.1 Integer
34
  INTEGER       = 0x02,
35
  /// \brief ASN.1 Bit string
36
  BIT_STRING      = 0x03,
37
  /// \brief ASN.1 Octet string
38
  OCTET_STRING    = 0x04,
39
  /// \brief ASN.1 Null
40
  TAG_NULL      = 0x05,
41
  /// \brief ASN.1 Object identifier
42
  OBJECT_IDENTIFIER = 0x06,
43
  /// \brief ASN.1 Object descriptor
44
  OBJECT_DESCRIPTOR = 0x07,
45
  /// \brief ASN.1 External reference
46
  EXTERNAL      = 0x08,
47
  /// \brief ASN.1 Real integer
48
  REAL        = 0x09,
49
  /// \brief ASN.1 Enumerated value
50
  ENUMERATED      = 0x0a,
51
  /// \brief ASN.1 UTF-8 string
52
  UTF8_STRING     = 0x0c,
53
  /// \brief ASN.1 Sequence
54
  SEQUENCE      = 0x10,
55
  /// \brief ASN.1 Set
56
  SET         = 0x11,
57
  /// \brief ASN.1 Numeric string
58
  NUMERIC_STRING    = 0x12,
59
  /// \brief ASN.1 Printable string
60
  PRINTABLE_STRING  = 0x13,
61
  /// \brief ASN.1 T61 string
62
  T61_STRING      = 0x14,
63
  /// \brief ASN.1 Videotext string
64
  VIDEOTEXT_STRING  = 0x15,
65
  /// \brief ASN.1 IA5 string
66
  IA5_STRING      = 0x16,
67
  /// \brief ASN.1 UTC time
68
  UTC_TIME      = 0x17,
69
  /// \brief ASN.1 Generalized time
70
  GENERALIZED_TIME  = 0x18,
71
  /// \brief ASN.1 Graphic string
72
  GRAPHIC_STRING    = 0x19,
73
  /// \brief ASN.1 Visible string
74
  VISIBLE_STRING    = 0x1a,
75
  /// \brief ASN.1 General string
76
  GENERAL_STRING    = 0x1b,
77
  /// \brief ASN.1 Universal string
78
  UNIVERSAL_STRING  = 0x1c,
79
  /// \brief ASN.1 BMP string
80
  BMP_STRING      = 0x1e
81
};
82
83
/// \brief ASN.1 flags
84
/// \note These flags are not complete
85
enum ASNIdFlag
86
{
87
  /// \brief ASN.1 Universal class
88
  UNIVERSAL           = 0x00,
89
  // DATA           = 0x01,
90
  // HEADER           = 0x02,
91
  /// \brief ASN.1 Primitive flag
92
  PRIMITIVE           = 0x00,
93
  /// \brief ASN.1 Constructed flag
94
  CONSTRUCTED         = 0x20,
95
  /// \brief ASN.1 Application class
96
  APPLICATION         = 0x40,
97
  /// \brief ASN.1 Context specific class
98
  CONTEXT_SPECIFIC    = 0x80,
99
  /// \brief ASN.1 Private class
100
  PRIVATE             = 0xc0
101
};
102
103
/// \brief Raises a BERDecodeErr
104
0
inline void BERDecodeError() {throw BERDecodeErr();}
105
106
/// \brief Exception thrown when an unknown object identifier is encountered
107
class CRYPTOPP_DLL UnknownOID : public BERDecodeErr
108
{
109
public:
110
  /// \brief Construct an UnknownOID
111
1.23k
  UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {}
112
  /// \brief Construct an UnknownOID
113
  /// \param err error message to use for the exception
114
0
  UnknownOID(const char *err) : BERDecodeErr(err) {}
115
};
116
117
/// \brief DER encode a length
118
/// \param bt BufferedTransformation object for writing
119
/// \param length the size to encode
120
/// \return the number of octets used for the encoding
121
CRYPTOPP_DLL size_t CRYPTOPP_API DERLengthEncode(BufferedTransformation &bt, lword length);
122
123
/// \brief BER decode a length
124
/// \param bt BufferedTransformation object for reading
125
/// \param length the decoded size
126
/// \return true if the value was decoded
127
/// \throw BERDecodeError if the value fails to decode or is too large for size_t
128
/// \details BERLengthDecode() returns false if the encoding is indefinite length.
129
CRYPTOPP_DLL bool CRYPTOPP_API BERLengthDecode(BufferedTransformation &bt, size_t &length);
130
131
/// \brief DER encode NULL
132
/// \param bt BufferedTransformation object for writing
133
CRYPTOPP_DLL void CRYPTOPP_API DEREncodeNull(BufferedTransformation &bt);
134
135
/// \brief BER decode NULL
136
/// \param bt BufferedTransformation object for reading
137
CRYPTOPP_DLL void CRYPTOPP_API BERDecodeNull(BufferedTransformation &bt);
138
139
/// \brief DER encode octet string
140
/// \param bt BufferedTransformation object for writing
141
/// \param str the string to encode
142
/// \param strLen the length of the string
143
/// \return the number of octets used for the encoding
144
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen);
145
146
/// \brief DER encode octet string
147
/// \param bt BufferedTransformation object for reading
148
/// \param str the string to encode
149
/// \return the number of octets used for the encoding
150
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str);
151
152
/// \brief BER decode octet string
153
/// \param bt BufferedTransformation object for reading
154
/// \param str the decoded string
155
/// \return the number of octets used for the encoding
156
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str);
157
158
/// \brief BER decode octet string
159
/// \param bt BufferedTransformation object for reading
160
/// \param str the decoded string
161
/// \return the number of octets used for the encoding
162
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str);
163
164
/// \brief DER encode text string
165
/// \param bt BufferedTransformation object for writing
166
/// \param str the string to encode
167
/// \param strLen the length of the string, in bytes
168
/// \param asnTag the ASN.1 identifier
169
/// \return the number of octets used for the encoding
170
/// \details DEREncodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
171
/// \since Crypto++ 8.3
172
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &bt, const byte* str, size_t strLen, byte asnTag);
173
174
/// \brief DER encode text string
175
/// \param bt BufferedTransformation object for writing
176
/// \param str the string to encode
177
/// \param asnTag the ASN.1 identifier
178
/// \return the number of octets used for the encoding
179
/// \details DEREncodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
180
/// \since Crypto++ 8.3
181
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &bt, const SecByteBlock &str, byte asnTag);
182
183
/// \brief DER encode text string
184
/// \param bt BufferedTransformation object for writing
185
/// \param str the string to encode
186
/// \param asnTag the ASN.1 identifier
187
/// \return the number of octets used for the encoding
188
/// \details DEREncodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
189
/// \since Crypto++ 6.0
190
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag);
191
192
/// \brief BER decode text string
193
/// \param bt BufferedTransformation object for reading
194
/// \param str the string to decode
195
/// \param asnTag the ASN.1 identifier
196
/// \details BERDecodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
197
/// \since Crypto++ 8.3
198
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &bt, SecByteBlock &str, byte asnTag);
199
200
/// \brief BER decode text string
201
/// \param bt BufferedTransformation object for reading
202
/// \param str the string to decode
203
/// \param asnTag the ASN.1 identifier
204
/// \details BERDecodeTextString() can be used for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
205
/// \since Crypto++ 6.0
206
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag);
207
208
/// \brief DER encode date
209
/// \param bt BufferedTransformation object for writing
210
/// \param str the date to encode
211
/// \param asnTag the ASN.1 identifier
212
/// \return the number of octets used for the encoding
213
/// \details BERDecodeDate() can be used for UTC_TIME and GENERALIZED_TIME
214
/// \since Crypto++ 8.3
215
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeDate(BufferedTransformation &bt, const SecByteBlock &str, byte asnTag);
216
217
/// \brief BER decode date
218
/// \param bt BufferedTransformation object for reading
219
/// \param str the date to decode
220
/// \param asnTag the ASN.1 identifier
221
/// \details BERDecodeDate() can be used for UTC_TIME and GENERALIZED_TIME
222
/// \since Crypto++ 8.3
223
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeDate(BufferedTransformation &bt, SecByteBlock &str, byte asnTag);
224
225
/// \brief DER encode bit string
226
/// \param bt BufferedTransformation object for writing
227
/// \param str the string to encode
228
/// \param strLen the length of the string
229
/// \param unusedBits the number of unused bits
230
/// \return the number of octets used for the encoding
231
/// \details The caller is responsible for shifting octets if unusedBits is
232
///  not 0. For example, to DER encode a web server X.509 key usage, the 101b
233
///  bit mask is often used (digitalSignature and keyEncipherment). In this
234
///  case <tt>str</tt> is one octet with a value=0xa0 and unusedBits=5. The
235
///  value 0xa0 is <tt>101b << 5</tt>.
236
CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits=0);
237
238
/// \brief DER decode bit string
239
/// \param bt BufferedTransformation object for reading
240
/// \param str the decoded string
241
/// \param unusedBits the number of unused bits
242
/// \details The caller is responsible for shifting octets if unusedBits is
243
///  not 0. For example, to DER encode a web server X.509 key usage, the 101b
244
///  bit mask is often used (digitalSignature and keyEncipherment). In this
245
///  case <tt>str</tt> is one octet with a value=0xa0 and unusedBits=5. The
246
///  value 0xa0 is <tt>101b << 5</tt>.
247
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits);
248
249
/// \brief BER decode and DER re-encode
250
/// \param bt BufferedTransformation object for writing
251
/// \param dest BufferedTransformation object
252
CRYPTOPP_DLL void CRYPTOPP_API DERReencode(BufferedTransformation &bt, BufferedTransformation &dest);
253
254
/// \brief BER decode size
255
/// \param bt BufferedTransformation object for reading
256
/// \return the length of the ASN.1 value, in bytes
257
/// \details BERDecodePeekLength() determines the length of a value without
258
///  consuming octets in the stream. The stream must use definite length encoding.
259
///  If indefinite length encoding is used or an error occurs, then 0 is returned.
260
/// \since Crypto++ 8.3
261
CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodePeekLength(const BufferedTransformation &bt);
262
263
/// \brief Object Identifier
264
class CRYPTOPP_DLL OID
265
{
266
public:
267
384k
  virtual ~OID() {}
268
269
  /// \brief Construct an OID
270
30.7k
  OID() {}
271
272
  /// \brief Construct an OID
273
  /// \param v value to initialize the OID
274
28.5k
  OID(word32 v) : m_values(1, v) {}
275
276
  /// \brief Construct an OID
277
  /// \param bt BufferedTransformation object
278
0
  OID(BufferedTransformation &bt) {
279
0
    BERDecode(bt);
280
0
  }
281
282
  /// \brief Append a value to an OID
283
  /// \param rhs the value to append
284
162k
  inline OID & operator+=(word32 rhs) {
285
162k
    m_values.push_back(rhs); return *this;
286
162k
  }
287
288
  /// \brief DER encode this OID
289
  /// \param bt BufferedTransformation object
290
  void DEREncode(BufferedTransformation &bt) const;
291
292
  /// \brief BER decode an OID
293
  /// \param bt BufferedTransformation object
294
  void BERDecode(BufferedTransformation &bt);
295
296
  /// \brief BER decode an OID
297
  /// \param bt BufferedTransformation object
298
  /// \throw BERDecodeErr() if decoded value doesn't match an expected OID
299
  /// \details BERDecodeAndCheck() can be used to parse an OID and verify it matches an expected.
300
  /// <pre>
301
  ///   BERSequenceDecoder key(bt);
302
  ///   ...
303
  ///   BERSequenceDecoder algorithm(key);
304
  ///   GetAlgorithmID().BERDecodeAndCheck(algorithm);
305
  /// </pre>
306
  void BERDecodeAndCheck(BufferedTransformation &bt) const;
307
308
  /// \brief Determine if OID is empty
309
  /// \return true if OID has 0 elements, false otherwise
310
  /// \since Crypto++ 8.0
311
0
  bool Empty() const {
312
0
    return m_values.empty();
313
0
  }
314
315
  /// \brief Retrieve OID value array
316
  /// \return OID value vector
317
  /// \since Crypto++ 8.0
318
0
  const std::vector<word32>& GetValues() const {
319
0
    return m_values;
320
0
  }
321
322
  /// \brief Print an OID
323
  /// \param out ostream object
324
  /// \return ostream reference
325
  /// \details Print() writes the OID in a customary format, like
326
  ///  1.2.840.113549.1.1.11. The caller is reposnsible to convert the
327
  ///  OID to a friendly name, like sha256WithRSAEncryption.
328
  /// \since Crypto++ 8.3
329
  std::ostream& Print(std::ostream& out) const;
330
331
protected:
332
  friend bool operator==(const OID &lhs, const OID &rhs);
333
  friend bool operator!=(const OID &lhs, const OID &rhs);
334
  friend bool operator< (const OID &lhs, const OID &rhs);
335
  friend bool operator> (const OID &lhs, const OID &rhs);
336
  friend bool operator<=(const OID &lhs, const OID &rhs);
337
  friend bool operator>=(const OID &lhs, const OID &rhs);
338
339
  std::vector<word32> m_values;
340
341
private:
342
  static void EncodeValue(BufferedTransformation &bt, word32 v);
343
  static size_t DecodeValue(BufferedTransformation &bt, word32 &v);
344
};
345
346
/// \brief ASN.1 encoded object filter
347
class EncodedObjectFilter : public Filter
348
{
349
public:
350
  enum Flag {PUT_OBJECTS=1, PUT_MESSANGE_END_AFTER_EACH_OBJECT=2, PUT_MESSANGE_END_AFTER_ALL_OBJECTS=4, PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS=8};
351
  enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state;
352
353
0
  virtual ~EncodedObjectFilter() {}
354
355
  /// \brief Construct an EncodedObjectFilter
356
  /// \param attachment a BufferedTrasformation to attach to this object
357
  /// \param nObjects the number of objects
358
  /// \param flags bitwise OR of EncodedObjectFilter::Flag
359
  EncodedObjectFilter(BufferedTransformation *attachment = NULLPTR, unsigned int nObjects = 1, word32 flags = 0);
360
361
  /// \brief Input a byte buffer for processing
362
  /// \param inString the byte buffer to process
363
  /// \param length the size of the string, in bytes
364
  void Put(const byte *inString, size_t length);
365
366
0
  unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;}
367
0
  unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];}
368
369
private:
370
  BufferedTransformation & CurrentTarget();
371
372
  ByteQueue m_queue;
373
  std::vector<unsigned int> m_positions;
374
  lword m_lengthRemaining;
375
  word32 m_nObjects, m_nCurrentObject, m_level, m_flags;
376
  byte m_id;
377
};
378
379
/// \brief BER General Decoder
380
class CRYPTOPP_DLL BERGeneralDecoder : public Store
381
{
382
public:
383
  /// \brief Default ASN.1 tag
384
  enum {DefaultTag = SEQUENCE | EnumToInt(CONSTRUCTED)};
385
386
  virtual ~BERGeneralDecoder();
387
388
  /// \brief Construct an ASN.1 decoder
389
  /// \param inQueue input byte queue
390
  /// \details BERGeneralDecoder uses DefaultTag
391
  explicit BERGeneralDecoder(BufferedTransformation &inQueue);
392
393
  /// \brief Construct an ASN.1 decoder
394
  /// \param inQueue input byte queue
395
  /// \param asnTag ASN.1 tag
396
  explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag);
397
398
  /// \brief Construct an ASN.1 decoder
399
  /// \param inQueue input byte queue
400
  /// \param asnTag ASN.1 tag
401
  explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag);
402
403
  /// \brief Determine length encoding
404
  /// \return true if the ASN.1 object is definite length encoded, false otherwise
405
0
  bool IsDefiniteLength() const {
406
0
    return m_definiteLength;
407
0
  }
408
409
  /// \brief Determine remaining length
410
  /// \return number of octets that remain to be consumed
411
  /// \details RemainingLength() is only valid if IsDefiniteLength()
412
  ///  returns true.
413
0
  lword RemainingLength() const {
414
0
    CRYPTOPP_ASSERT(m_definiteLength);
415
0
    return IsDefiniteLength() ? m_length : 0;
416
0
  }
417
418
  /// \brief Determine end of stream
419
  /// \return true if all octets have been consumed, false otherwise
420
  bool EndReached() const;
421
422
  /// \brief Determine next octet
423
  /// \return next octet in the stream
424
  /// \details PeekByte does not consume the octet.
425
  /// \throw BERDecodeError if there are no octets remaining
426
  byte PeekByte() const;
427
428
  /// \brief Determine next octet
429
  /// \details CheckByte reads the next byte in the stream and verifies
430
  ///  the octet matches b.
431
  /// \throw BERDecodeError if the next octet is not b
432
  void CheckByte(byte b);
433
434
  /// \brief Transfer bytes to another BufferedTransformation
435
  /// \param target the destination BufferedTransformation
436
  /// \param transferBytes the number of bytes to transfer
437
  /// \param channel the channel on which the transfer should occur
438
  /// \param blocking specifies whether the object should block when
439
  ///  processing input
440
  /// \return the number of bytes that remain in the transfer block
441
  ///  (i.e., bytes not transferred)
442
  /// \details TransferTo2() removes bytes and moves
443
  ///  them to the destination. Transfer begins at the index position
444
  ///  in the current stream, and not from an absolute position in the
445
  ///  stream.
446
  /// \details transferBytes is an \a IN and \a OUT parameter. When
447
  ///  the call is made, transferBytes is the requested size of the
448
  ///  transfer. When the call returns, transferBytes is the number
449
  ///  of bytes that were transferred.
450
  size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
451
452
  /// \brief Copy bytes to another BufferedTransformation
453
  /// \param target the destination BufferedTransformation
454
  /// \param begin the 0-based index of the first byte to copy in
455
  ///  the stream
456
  /// \param end the 0-based index of the last byte to copy in
457
  ///  the stream
458
  /// \param channel the channel on which the transfer should occur
459
  /// \param blocking specifies whether the object should block when
460
  ///  processing input
461
  /// \return the number of bytes that remain in the copy block
462
  ///  (i.e., bytes not copied)
463
  /// \details CopyRangeTo2 copies bytes to the
464
  ///  destination. The bytes are not removed from this object. Copying
465
  ///  begins at the index position in the current stream, and not from
466
  ///  an absolute position in the stream.
467
  /// \details begin is an \a IN and \a OUT parameter. When the call is
468
  ///  made, begin is the starting position of the copy. When the call
469
  ///  returns, begin is the position of the first byte that was \a not
470
  ///  copied (which may be different than end). begin can be used for
471
  ///  subsequent calls to CopyRangeTo2().
472
  size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
473
474
  /// \brief Signals the end of messages to the object
475
  /// \details Call this to denote end of sequence
476
  void MessageEnd();
477
478
protected:
479
  BufferedTransformation &m_inQueue;
480
  lword m_length;
481
  bool m_finished, m_definiteLength;
482
483
private:
484
  void Init(byte asnTag);
485
  void StoreInitialize(const NameValuePairs &parameters)
486
0
    {CRYPTOPP_UNUSED(parameters); CRYPTOPP_ASSERT(false);}
487
  lword ReduceLength(lword delta);
488
};
489
490
/// \brief DER General Encoder
491
class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue
492
{
493
public:
494
  /// \brief Default ASN.1 tag
495
  enum {DefaultTag = SEQUENCE | EnumToInt(CONSTRUCTED)};
496
497
  virtual ~DERGeneralEncoder();
498
499
  /// \brief Construct an ASN.1 encoder
500
  /// \param outQueue output byte queue
501
  /// \details DERGeneralEncoder uses DefaultTag
502
  explicit DERGeneralEncoder(BufferedTransformation &outQueue);
503
504
  /// \brief Construct an ASN.1 encoder
505
  /// \param outQueue output byte queue
506
  /// \param asnTag ASN.1 tag
507
  explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag);
508
509
  /// \brief Construct an ASN.1 encoder
510
  /// \param outQueue output byte queue
511
  /// \param asnTag ASN.1 tag
512
  explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag);
513
514
  /// \brief Signals the end of messages to the object
515
  /// \details Call this to denote end of sequence
516
  void MessageEnd();
517
518
private:
519
  BufferedTransformation &m_outQueue;
520
  byte m_asnTag;
521
  bool m_finished;
522
};
523
524
/// \brief BER Sequence Decoder
525
class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder
526
{
527
public:
528
  /// \brief Default ASN.1 tag
529
  enum {DefaultTag = SEQUENCE | EnumToInt(CONSTRUCTED)};
530
531
  /// \brief Construct an ASN.1 decoder
532
  /// \param inQueue input byte queue
533
  /// \details BERSequenceDecoder uses DefaultTag
534
  explicit BERSequenceDecoder(BufferedTransformation &inQueue)
535
0
    : BERGeneralDecoder(inQueue, DefaultTag) {}
536
537
  /// \brief Construct an ASN.1 decoder
538
  /// \param inQueue input byte queue
539
  /// \param asnTag ASN.1 tag
540
  explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag)
541
0
    : BERGeneralDecoder(inQueue, asnTag) {}
542
543
  /// \brief Construct an ASN.1 decoder
544
  /// \param inQueue input byte queue
545
  /// \details BERSequenceDecoder uses DefaultTag
546
  explicit BERSequenceDecoder(BERSequenceDecoder &inQueue)
547
0
    : BERGeneralDecoder(inQueue, DefaultTag) {}
548
549
  /// \brief Construct an ASN.1 decoder
550
  /// \param inQueue input byte queue
551
  /// \param asnTag ASN.1 tag
552
  explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag)
553
0
    : BERGeneralDecoder(inQueue, asnTag) {}
554
};
555
556
/// \brief DER Sequence Encoder
557
class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder
558
{
559
public:
560
  /// \brief Default ASN.1 tag
561
  enum {DefaultTag = SEQUENCE | EnumToInt(CONSTRUCTED)};
562
563
  /// \brief Construct an ASN.1 encoder
564
  /// \param outQueue output byte queue
565
  /// \details DERSequenceEncoder uses DefaultTag
566
  explicit DERSequenceEncoder(BufferedTransformation &outQueue)
567
0
    : DERGeneralEncoder(outQueue, DefaultTag) {}
568
569
  /// \brief Construct an ASN.1 encoder
570
  /// \param outQueue output byte queue
571
  /// \param asnTag ASN.1 tag
572
  explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag)
573
0
    : DERGeneralEncoder(outQueue, asnTag) {}
574
575
  /// \brief Construct an ASN.1 encoder
576
  /// \param outQueue output byte queue
577
  /// \details DERSequenceEncoder uses DefaultTag
578
  explicit DERSequenceEncoder(DERSequenceEncoder &outQueue)
579
0
    : DERGeneralEncoder(outQueue, DefaultTag) {}
580
581
  /// \brief Construct an ASN.1 encoder
582
  /// \param outQueue output byte queue
583
  /// \param asnTag ASN.1 tag
584
  explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag)
585
0
    : DERGeneralEncoder(outQueue, asnTag) {}
586
};
587
588
/// \brief BER Set Decoder
589
class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder
590
{
591
public:
592
  /// \brief Default ASN.1 tag
593
  enum {DefaultTag = SET | EnumToInt(CONSTRUCTED)};
594
595
  /// \brief Construct an ASN.1 decoder
596
  /// \param inQueue input byte queue
597
  /// \details BERSetDecoder uses DefaultTag
598
  explicit BERSetDecoder(BufferedTransformation &inQueue)
599
0
    : BERGeneralDecoder(inQueue, DefaultTag) {}
600
601
  /// \brief Construct an ASN.1 decoder
602
  /// \param inQueue input byte queue
603
  /// \param asnTag ASN.1 tag
604
  explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag)
605
0
    : BERGeneralDecoder(inQueue, asnTag) {}
606
607
  /// \brief Construct an ASN.1 decoder
608
  /// \param inQueue input byte queue
609
  /// \details BERSetDecoder uses DefaultTag
610
  explicit BERSetDecoder(BERSetDecoder &inQueue)
611
0
    : BERGeneralDecoder(inQueue, DefaultTag) {}
612
613
  /// \brief Construct an ASN.1 decoder
614
  /// \param inQueue input byte queue
615
  /// \param asnTag ASN.1 tag
616
  explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag)
617
0
    : BERGeneralDecoder(inQueue, asnTag) {}
618
};
619
620
/// \brief DER Set Encoder
621
class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder
622
{
623
public:
624
  /// \brief Default ASN.1 tag
625
  enum {DefaultTag = SET | EnumToInt(CONSTRUCTED)};
626
627
  /// \brief Construct an ASN.1 encoder
628
  /// \param outQueue output byte queue
629
  /// \details DERSetEncoder uses DefaultTag
630
  explicit DERSetEncoder(BufferedTransformation &outQueue)
631
0
    : DERGeneralEncoder(outQueue, DefaultTag) {}
632
633
  /// \brief Construct an ASN.1 encoder
634
  /// \param outQueue output byte queue
635
  /// \param asnTag ASN.1 tag
636
  explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag)
637
0
    : DERGeneralEncoder(outQueue, asnTag) {}
638
639
  /// \brief Construct an ASN.1 encoder
640
  /// \param outQueue output byte queue
641
  /// \details DERSetEncoder uses DefaultTag
642
  explicit DERSetEncoder(DERSetEncoder &outQueue)
643
0
    : DERGeneralEncoder(outQueue, DefaultTag) {}
644
645
  /// \brief Construct an ASN.1 encoder
646
  /// \param outQueue output byte queue
647
  /// \param asnTag ASN.1 tag
648
  explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag)
649
0
    : DERGeneralEncoder(outQueue, asnTag) {}
650
};
651
652
/// \brief Optional data encoder and decoder
653
/// \tparam T class or type
654
template <class T>
655
class ASNOptional : public member_ptr<T>
656
{
657
public:
658
  /// \brief BER decode optional data
659
  /// \param seqDecoder sequence with the optional ASN.1 data
660
  /// \param tag ASN.1 tag to match as optional data
661
  /// \param mask the mask to apply when matching the tag
662
  /// \sa ASNTag and ASNIdFlag
663
  void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED)
664
  {
665
    byte b;
666
    if (seqDecoder.Peek(b) && (b & mask) == tag)
667
      reset(new T(seqDecoder));
668
  }
669
670
  /// \brief DER encode optional data
671
  /// \param out BufferedTransformation object
672
  void DEREncode(BufferedTransformation &out)
673
  {
674
    if (this->get() != NULLPTR)
675
      this->get()->DEREncode(out);
676
  }
677
};
678
679
/// \brief Encode and decode ASN.1 objects with additional information
680
/// \tparam BASE base class or type
681
/// \details Encodes and decodes public keys, private keys and group
682
///   parameters with OID identifying the algorithm or scheme.
683
template <class BASE>
684
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1CryptoMaterial : public ASN1Object, public BASE
685
{
686
public:
687
  /// \brief DER encode ASN.1 object
688
  /// \param bt BufferedTransformation object
689
  /// \details Save() will write the OID associated with algorithm or scheme.
690
  ///   In the case of public and private keys, this function writes the
691
  ///   subjectPublicKeyInfo and privateKeyInfo parts.
692
  void Save(BufferedTransformation &bt) const
693
0
    {BEREncode(bt);}
Unexecuted instantiation: CryptoPP::ASN1CryptoMaterial<CryptoPP::PublicKey>::Save(CryptoPP::BufferedTransformation&) const
Unexecuted instantiation: CryptoPP::ASN1CryptoMaterial<CryptoPP::PrivateKey>::Save(CryptoPP::BufferedTransformation&) const
Unexecuted instantiation: CryptoPP::ASN1CryptoMaterial<CryptoPP::DL_GroupParameters<CryptoPP::Integer> >::Save(CryptoPP::BufferedTransformation&) const
694
695
  /// \brief BER decode ASN.1 object
696
  /// \param bt BufferedTransformation object
697
  void Load(BufferedTransformation &bt)
698
0
    {BERDecode(bt);}
Unexecuted instantiation: CryptoPP::ASN1CryptoMaterial<CryptoPP::PublicKey>::Load(CryptoPP::BufferedTransformation&)
Unexecuted instantiation: CryptoPP::ASN1CryptoMaterial<CryptoPP::PrivateKey>::Load(CryptoPP::BufferedTransformation&)
Unexecuted instantiation: CryptoPP::ASN1CryptoMaterial<CryptoPP::DL_GroupParameters<CryptoPP::Integer> >::Load(CryptoPP::BufferedTransformation&)
699
};
700
701
/// \brief Encodes and decodes subjectPublicKeyInfo
702
class CRYPTOPP_DLL X509PublicKey : public ASN1CryptoMaterial<PublicKey>
703
{
704
public:
705
1.26k
  virtual ~X509PublicKey() {}
706
707
  void BERDecode(BufferedTransformation &bt);
708
  void DEREncode(BufferedTransformation &bt) const;
709
710
  /// \brief Retrieves the OID of the algorithm
711
  /// \return OID of the algorithm
712
  virtual OID GetAlgorithmID() const =0;
713
714
  /// \brief Decode algorithm parameters
715
  /// \param bt BufferedTransformation object
716
  /// \sa BERDecodePublicKey, <A HREF="http://www.ietf.org/rfc/rfc2459.txt">RFC
717
  ///  2459, section 7.3.1</A>
718
  virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
719
0
    {BERDecodeNull(bt); return false;}
720
721
  /// \brief Encode algorithm parameters
722
  /// \param bt BufferedTransformation object
723
  /// \sa DEREncodePublicKey, <A HREF="http://www.ietf.org/rfc/rfc2459.txt">RFC
724
  ///  2459, section 7.3.1</A>
725
  virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
726
0
    {DEREncodeNull(bt); return false;}
727
728
  /// \brief Decode subjectPublicKey part of subjectPublicKeyInfo
729
  /// \param bt BufferedTransformation object
730
  /// \param parametersPresent flag indicating if algorithm parameters are present
731
  /// \param size number of octets to read for the parameters, in bytes
732
  /// \details BERDecodePublicKey() the decodes subjectPublicKey part of
733
  ///  subjectPublicKeyInfo, without the BIT STRING header.
734
  /// \details When <tt>parametersPresent = true</tt> then BERDecodePublicKey() calls
735
  ///  BERDecodeAlgorithmParameters() to parse algorithm parameters.
736
  /// \sa BERDecodeAlgorithmParameters
737
  virtual void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
738
739
  /// \brief Encode subjectPublicKey part of subjectPublicKeyInfo
740
  /// \param bt BufferedTransformation object
741
  /// \details DEREncodePublicKey() encodes the subjectPublicKey part of
742
  ///  subjectPublicKeyInfo, without the BIT STRING header.
743
  /// \sa DEREncodeAlgorithmParameters
744
  virtual void DEREncodePublicKey(BufferedTransformation &bt) const =0;
745
};
746
747
/// \brief Encodes and Decodes privateKeyInfo
748
class CRYPTOPP_DLL PKCS8PrivateKey : public ASN1CryptoMaterial<PrivateKey>
749
{
750
public:
751
1.01k
  virtual ~PKCS8PrivateKey() {}
752
753
  void BERDecode(BufferedTransformation &bt);
754
  void DEREncode(BufferedTransformation &bt) const;
755
756
  /// \brief Retrieves the OID of the algorithm
757
  /// \return OID of the algorithm
758
  virtual OID GetAlgorithmID() const =0;
759
760
  /// \brief Decode optional parameters
761
  /// \param bt BufferedTransformation object
762
  /// \sa BERDecodePrivateKey, <A HREF="http://www.ietf.org/rfc/rfc2459.txt">RFC
763
  ///  2459, section 7.3.1</A>
764
  virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
765
0
    {BERDecodeNull(bt); return false;}
766
767
  /// \brief Encode optional parameters
768
  /// \param bt BufferedTransformation object
769
  /// \sa DEREncodePrivateKey, <A HREF="http://www.ietf.org/rfc/rfc2459.txt">RFC
770
  ///  2459, section 7.3.1</A>
771
  virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
772
0
    {DEREncodeNull(bt); return false;}
773
774
  /// \brief Decode privateKey part of privateKeyInfo
775
  /// \param bt BufferedTransformation object
776
  /// \param parametersPresent flag indicating if algorithm parameters are present
777
  /// \param size number of octets to read for the parameters, in bytes
778
  /// \details BERDecodePrivateKey() the decodes privateKey part of privateKeyInfo,
779
  ///  without the OCTET STRING header.
780
  /// \details When <tt>parametersPresent = true</tt> then BERDecodePrivateKey() calls
781
  ///  BERDecodeAlgorithmParameters() to parse algorithm parameters.
782
  /// \sa BERDecodeAlgorithmParameters
783
  virtual void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0;
784
785
  /// \brief Encode privateKey part of privateKeyInfo
786
  /// \param bt BufferedTransformation object
787
  /// \details DEREncodePrivateKey() encodes the privateKey part of privateKeyInfo,
788
  ///  without the OCTET STRING header.
789
  /// \sa DEREncodeAlgorithmParameters
790
  virtual void DEREncodePrivateKey(BufferedTransformation &bt) const =0;
791
792
  /// \brief Decode optional attributes
793
  /// \param bt BufferedTransformation object
794
  /// \details BERDecodeOptionalAttributes() decodes optional attributes including
795
  ///  context-specific tag.
796
  /// \sa BERDecodeAlgorithmParameters, DEREncodeOptionalAttributes
797
  /// \note default implementation stores attributes to be output using
798
  ///  DEREncodeOptionalAttributes
799
  virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt);
800
801
  /// \brief Encode optional attributes
802
  /// \param bt BufferedTransformation object
803
  /// \details DEREncodeOptionalAttributes() encodes optional attributes including
804
  ///  context-specific tag.
805
  /// \sa BERDecodeAlgorithmParameters
806
  virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const;
807
808
protected:
809
  ByteQueue m_optionalAttributes;
810
};
811
812
// ********************************************************
813
814
/// \brief DER Encode unsigned value
815
/// \tparam T class or type
816
/// \param out BufferedTransformation object
817
/// \param w unsigned value to encode
818
/// \param asnTag the ASN.1 identifier
819
/// \details DEREncodeUnsigned() can be used with INTEGER, BOOLEAN, and ENUM
820
template <class T>
821
size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER)
822
0
{
823
0
  byte buf[sizeof(w)+1];
824
0
  unsigned int bc;
825
0
  if (asnTag == BOOLEAN)
826
0
  {
827
0
    buf[sizeof(w)] = w ? 0xff : 0;
828
0
    bc = 1;
829
0
  }
830
0
  else
831
0
  {
832
0
    buf[0] = 0;
833
0
    for (unsigned int i=0; i<sizeof(w); i++)
834
0
      buf[i+1] = byte(w >> (sizeof(w)-1-i)*8);
835
0
    bc = sizeof(w);
836
0
    while (bc > 1 && buf[sizeof(w)+1-bc] == 0)
837
0
      --bc;
838
0
    if (buf[sizeof(w)+1-bc] & 0x80)
839
0
      ++bc;
840
0
  }
841
0
  out.Put(asnTag);
842
0
  size_t lengthBytes = DERLengthEncode(out, bc);
843
0
  out.Put(buf+sizeof(w)+1-bc, bc);
844
0
  return 1+lengthBytes+bc;
845
0
}
Unexecuted instantiation: unsigned long CryptoPP::DEREncodeUnsigned<unsigned int>(CryptoPP::BufferedTransformation&, unsigned int, unsigned char)
Unexecuted instantiation: unsigned long CryptoPP::DEREncodeUnsigned<CryptoPP::Integer::RandomNumberType>(CryptoPP::BufferedTransformation&, CryptoPP::Integer::RandomNumberType, unsigned char)
846
847
/// \brief BER Decode unsigned value
848
/// \tparam T fundamental C++ type
849
/// \param in BufferedTransformation object
850
/// \param w the decoded value
851
/// \param asnTag the ASN.1 identifier
852
/// \param minValue the minimum expected value
853
/// \param maxValue the maximum expected value
854
/// \throw BERDecodeErr() if the value cannot be parsed or the decoded value is not within range.
855
/// \details DEREncodeUnsigned() can be used with INTEGER, BOOLEAN, and ENUM
856
template <class T>
857
void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER,
858
             T minValue = 0, T maxValue = T(0xffffffff))
859
0
{
860
0
  byte b;
861
0
  if (!in.Get(b) || b != asnTag)
862
0
    BERDecodeError();
863
864
0
  size_t bc;
865
0
  bool definite = BERLengthDecode(in, bc);
866
0
  if (!definite)
867
0
    BERDecodeError();
868
0
  if (bc > in.MaxRetrievable())  // Issue 346
869
0
    BERDecodeError();
870
0
  if (asnTag == BOOLEAN && bc != 1) // X.690, 8.2.1
871
0
    BERDecodeError();
872
0
  if ((asnTag == INTEGER || asnTag == ENUMERATED) && bc == 0) // X.690, 8.3.1 and 8.4
873
0
    BERDecodeError();
874
875
0
  SecByteBlock buf(bc);
876
877
0
  if (bc != in.Get(buf, bc))
878
0
    BERDecodeError();
879
880
  // This consumes leading 0 octets. According to X.690, 8.3.2, it could be non-conforming behavior.
881
  //  X.690, 8.3.2 says "the bits of the first octet and bit 8 of the second octet ... (a) shall
882
  //  not all be ones and (b) shall not all be zeros ... These rules ensure that an integer value
883
  //  is always encoded in the smallest possible number of octet".
884
  // We invented AER (Alternate Encoding Rules), which is more relaxed than BER, CER, and DER.
885
0
  const byte *ptr = buf;
886
0
  while (bc > sizeof(w) && *ptr == 0)
887
0
  {
888
0
    bc--;
889
0
    ptr++;
890
0
  }
891
0
  if (bc > sizeof(w))
892
0
    BERDecodeError();
893
894
0
  w = 0;
895
0
  for (unsigned int i=0; i<bc; i++)
896
0
    w = (w << 8) | ptr[i];
897
898
0
  if (w < minValue || w > maxValue)
899
0
    BERDecodeError();
900
0
}
901
902
#ifdef CRYPTOPP_DOXYGEN_PROCESSING
903
/// \brief Compare two OIDs for equality
904
/// \param lhs the first OID
905
/// \param rhs the second OID
906
/// \return true if the OIDs are equal, false otherwise
907
inline bool operator==(const OID &lhs, const OID &rhs);
908
/// \brief Compare two OIDs for inequality
909
/// \param lhs the first OID
910
/// \param rhs the second OID
911
/// \return true if the OIDs are not equal, false otherwise
912
inline bool operator!=(const OID &lhs, const OID &rhs);
913
/// \brief Compare two OIDs for ordering
914
/// \param lhs the first OID
915
/// \param rhs the second OID
916
/// \return true if the first OID is less than the second OID, false otherwise
917
/// \details operator<() calls std::lexicographical_compare() on the values.
918
inline bool operator<(const OID &lhs, const OID &rhs);
919
/// \brief Compare two OIDs for ordering
920
/// \param lhs the first OID
921
/// \param rhs the second OID
922
/// \return true if the first OID is greater than the second OID, false otherwise
923
/// \details operator>() is implemented in terms of operator==() and operator<().
924
/// \since Crypto++ 8.3
925
inline bool operator>(const OID &lhs, const OID &rhs);
926
/// \brief Compare two OIDs for ordering
927
/// \param lhs the first OID
928
/// \param rhs the second OID
929
/// \return true if the first OID is less than or equal to the second OID, false otherwise
930
/// \details operator<=() is implemented in terms of operator==() and operator<().
931
/// \since Crypto++ 8.3
932
inline bool operator<=(const OID &lhs, const OID &rhs);
933
/// \brief Compare two OIDs for ordering
934
/// \param lhs the first OID
935
/// \param rhs the second OID
936
/// \return true if the first OID is greater than or equal to the second OID, false otherwise
937
/// \details operator>=() is implemented in terms of operator<().
938
/// \since Crypto++ 8.3
939
inline bool operator>=(const OID &lhs, const OID &rhs);
940
/// \brief Append a value to an OID
941
/// \param lhs the OID
942
/// \param rhs the value to append
943
inline OID operator+(const OID &lhs, unsigned long rhs);
944
/// \brief Print a OID value
945
/// \param out the output stream
946
/// \param oid the OID
947
inline std::ostream& operator<<(std::ostream& out, const OID &oid);
948
#else
949
inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
950
0
  {return lhs.m_values == rhs.m_values;}
951
inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
952
28.4k
  {return lhs.m_values != rhs.m_values;}
953
inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
954
134k
  {return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());}
955
inline bool operator>(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
956
0
  {return ! (lhs<rhs || lhs==rhs);}
957
inline bool operator<=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
958
0
  {return lhs<rhs || lhs==rhs;}
959
inline bool operator>=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
960
0
  {return ! (lhs<rhs);}
961
inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs)
962
162k
  {return ::CryptoPP::OID(lhs)+=rhs;}
963
inline std::ostream& operator<<(std::ostream& out, const OID &oid)
964
0
  { return oid.Print(out); }
965
#endif
966
967
NAMESPACE_END
968
969
// Issue 340
970
#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
971
# pragma GCC diagnostic pop
972
#endif
973
974
#endif