blob: 9620be276662daf658417a8895d941ca0fae67f7 [file] [log] [blame]
Jeff Thompsona92861a2013-10-16 14:06:23 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2013 Regents of the University of California.
4 * @author: Yingdi Yu <yingdi@cs.ucla.edu>
5 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
6 * See COPYING for copyright and distribution information.
7 */
8
9#if 1 // TODO: Remove this when we don't throw "not implemented".
10#include <stdexcept>
11#endif
12#include "der-exception.hpp"
13#include "../../util/logging.hpp"
14#include "der.hpp"
15
16INIT_LOGGER("ndn.der.DER");
17
18using namespace std;
19using namespace ndn::ptr_lib;
20
21namespace ndn {
22
23namespace der {
24
25/*
26 * DerNode
27 */
28DerNode::DerNode()
29 :m_parent(0)
30{}
31
32DerNode::DerNode(DerType type)
33 :m_type(type),
34 m_parent(0)
35{}
36
37DerNode::DerNode(std::istream& start)
38 :m_parent(0)
39{
40 decode(start);
41}
42
43DerNode::~DerNode()
44{}
45
46void
47DerNode::encodeHeader(int size)
48{
49 m_header.push_back((char)m_type);
50
51 if(size >= 127)
52 {
53 int val = size;
54 char buf[sizeof(val) + 1];
55 char *p = &(buf[sizeof(buf)-1]);
56 int n = 0;
57 int mask = (1 << 8) - 1;
58
59 while(val != 0)
60 {
61 p[0] = (char)(val & mask);
62 p--;
63 n++;
64 val >>= 8;
65 }
66
67 p[0] = (char)((1<<7) | n);
68 n++;
69
70 m_header.insert(m_header.end(), p, p+n);
71 }
72 else if(size >= 0)
73 {
74 m_header.push_back((char)size);
75 }
76 else
77 throw NegativeLengthException("Negative length");
78}
79
80int
81DerNode::decodeHeader(istream& start)
82{
83 uint8_t type = start.get();
84 // char type = start.get();
85 m_header.push_back(type);
86 m_type = static_cast<DerType>((int)type);
87
88 uint8_t sizeLen = start.get();
89 // char sizeLen = start.get();
90 m_header.push_back(sizeLen);
91
92 bool longFormat = sizeLen & (1 << 7);
93
94 if(!longFormat)
95 {
96 // _LOG_DEBUG("Short Format");
97 // _LOG_DEBUG("sizeLen: " << (int)sizeLen);
98 return (int)sizeLen;
99 }
100 else
101 {
102 // _LOG_DEBUG("Long Format");
103 uint8_t byte;
104 // char byte;
105 int lenCount = sizeLen & ((1<<7) - 1);
106 // _LOG_DEBUG("sizeLen: " << (int)sizeLen);
107 // _LOG_DEBUG("mask: " << (int)((1<<7) - 1));
108 // _LOG_DEBUG("lenCount: " << (int)lenCount);
109 int size = 0;
110 do
111 {
112 byte = start.get();
113 m_header.push_back(byte);
114 size = size * 256 + (int)byte;
115 // _LOG_DEBUG("byte: " << (int)byte);
116 // _LOG_DEBUG("size: " << size);
117 lenCount--;
118 }
119 while(lenCount > 0);
120
121 return size;
122 }
123}
124
125void
126DerNode::encode(ostream& start)
127{
128 start.write((const char*)&m_header[0], m_header.size());
129 start.write((const char*)&m_payload[0], m_payload.size());
130}
131
132void
133DerNode::decode(istream& start)
134{
135 int payloadSize = decodeHeader(start);
136 // _LOG_DEBUG("payloadSize: " << payloadSize);
137 if(payloadSize > 0 )
138 {
139 char buf[payloadSize];
140 start.read(buf, payloadSize);
141 m_payload.insert(m_payload.end(), buf, buf + payloadSize);
142 }
143}
144
145shared_ptr<DerNode>
146DerNode::parse(istream& start)
147{
148 int type = ((uint8_t)start.peek());
149
150 // _LOG_DEBUG("Type: " << hex << setw(2) << setfill('0') << type);
151 switch(type) {
152 case DER_BOOLEAN:
153 return shared_ptr<DerBool>(new DerBool(start));
154 case DER_INTEGER:
155 return shared_ptr<DerInteger>(new DerInteger(start));
156 case DER_BIT_STRING:
157 return shared_ptr<DerBitString>(new DerBitString(start));
158 case DER_OCTET_STRING:
159 return shared_ptr<DerOctetString>(new DerOctetString(start));
160 case DER_NULL:
161 return shared_ptr<DerNull>(new DerNull(start));
162 case DER_OBJECT_IDENTIFIER:
163 return shared_ptr<DerOid>(new DerOid(start));
164 case DER_SEQUENCE:
165 return shared_ptr<DerSequence>(new DerSequence(start));
166 case DER_PRINTABLE_STRING:
167 return shared_ptr<DerPrintableString>(new DerPrintableString(start));
168 case DER_GENERALIZED_TIME:
169 return shared_ptr<DerGtime>(new DerGtime(start));
170 default:
171 throw DerDecodingException("Unimplemented DER types");
172 }
173}
174
175
176/*
177 * DerComplex
178 */
179DerComplex::DerComplex()
180 :DerNode(),
181 m_childChanged(false),
182 m_size(0)
183{}
184
185DerComplex::DerComplex(DerType type)
186 :DerNode(type),
187 m_childChanged(false),
188 m_size(0)
189{}
190
191DerComplex::DerComplex(istream& start)
192 :DerNode(),
193 m_childChanged(false),
194 m_size(0)
195{
196 m_size = DerNode::decodeHeader(start);
197 // _LOG_DEBUG("Size: " << m_size);
198
199 int accSize = 0;
200
201 while(accSize < m_size)
202 {
203 // _LOG_DEBUG("accSize: " << accSize);
204 shared_ptr<DerNode> nodePtr = DerNode::parse(start);
205 accSize += nodePtr->getSize();
206 addChild(nodePtr, false);
207 }
208}
209
210DerComplex::~DerComplex()
211{}
212
213int
214DerComplex::getSize()
215{
216 if(m_childChanged)
217 {
218 updateSize();
219 m_childChanged = false;
220 }
221
222 m_header.clear();
223 DerNode::encodeHeader(m_size);
224 return m_size + m_header.size();
225}
226
227shared_ptr<vector<uint8_t> >
228DerComplex::getRaw()
229{
230 shared_ptr<vector<uint8_t> > blob(new vector<uint8_t>());
231 blob->insert(blob->end(), m_header.begin(), m_header.end());
232
233 DerNodePtrList::iterator it = m_nodeList.begin();
234 for(; it != m_nodeList.end(); it++)
235 {
236 shared_ptr<vector<uint8_t> > childBlob = (*it)->getRaw();
237 blob->insert(blob->end(), childBlob->begin(), childBlob->end());
238 }
239 return blob;
240}
241
242void
243DerComplex::updateSize()
244{
245 int newSize = 0;
246
247 DerNodePtrList::iterator it = m_nodeList.begin();
248 for(; it != m_nodeList.end(); it++)
249 {
250 newSize += (*it)->getSize();
251 }
252
253 m_size = newSize;
254 m_childChanged = false;
255}
256
257void
258DerComplex::addChild(shared_ptr<DerNode> nodePtr, bool notifyParent)
259{
260 nodePtr->setParent(this);
261
262 m_nodeList.push_back(nodePtr);
263
264 if(!notifyParent)
265 return;
266
267 if(m_childChanged)
268 return;
269 else
270 m_childChanged = true;
271
272 if(0 != m_parent)
273 m_parent->setChildChanged();
274}
275
276void
277DerComplex::setChildChanged()
278{
279 if(0 != m_parent && !m_childChanged)
280 {
281 m_parent->setChildChanged();
282 m_childChanged = true;
283 }
284 else
285 m_childChanged = true;
286}
287
288void
289DerComplex::encode(ostream& start)
290{
291 updateSize();
292 m_header.clear();
293
294 DerNode::encodeHeader(m_size);
295
296 start.write((const char*)&m_header[0], m_header.size());
297
298 DerNodePtrList::iterator it = m_nodeList.begin();
299 for(; it != m_nodeList.end(); it++)
300 (*it)->encode(start);
301}
302
303
304/*
305 * DerByteString
306 */
307DerByteString::DerByteString(const string& str, DerType type)
308 :DerNode(type)
309{
310 m_payload.insert(m_payload.end(), str.begin(), str.end());
311
312 DerNode::encodeHeader(m_payload.size());
313}
314
315DerByteString::DerByteString(const std::vector<uint8_t>& blob, DerType type)
316 :DerNode(type)
317{
318 m_payload.insert(m_payload.end(), blob.begin(), blob.end());
319
320 DerNode::encodeHeader(m_payload.size());
321}
322
323DerByteString::DerByteString(istream& start)
324 :DerNode(start)
325{}
326
327DerByteString::~DerByteString()
328{}
329
330
331/*
332 * DerBool
333 */
334DerBool::DerBool(bool value)
335 :DerNode(DER_BOOLEAN)
336
337{
338 char payload = (value ? 0xFF : 0x00);
339 m_payload.push_back(payload);
340
341 DerNode::encodeHeader(m_payload.size());
342}
343
344DerBool::DerBool(istream& start)
345 :DerNode(start)
346{}
347
348DerBool::~DerBool()
349{}
350
351
352/*
353 * DerInteger
354 */
355DerInteger::DerInteger(const vector<uint8_t>& blob)
356 :DerNode(DER_INTEGER)
357{
358 m_payload.insert(m_payload.end(), blob.begin(), blob.end());
359
360 DerNode::encodeHeader(m_payload.size());
361}
362
363DerInteger::DerInteger(istream& start)
364 :DerNode(start)
365{}
366
367DerInteger::~DerInteger()
368{}
369
370
371/*
372 * DerBitString
373 */
374DerBitString::DerBitString(const vector<uint8_t>& blob, uint8_t paddingLen)
375 :DerNode(DER_BIT_STRING)
376{
377 m_payload.push_back((char)paddingLen);
378 m_payload.insert(m_payload.end(), blob.begin(), blob.end());
379
380 DerNode::encodeHeader(m_payload.size());
381}
382
383DerBitString::DerBitString(istream& start)
384 :DerNode(start)
385{}
386
387DerBitString::~DerBitString()
388{}
389
390
391/*
392 * DerOctetString
393 */
394DerOctetString::DerOctetString(const string& str)
395 :DerByteString(str, DER_OCTET_STRING)
396{}
397
398DerOctetString::DerOctetString(const vector<uint8_t>& blob)
399 :DerByteString(blob, DER_OCTET_STRING)
400{}
401
402DerOctetString::DerOctetString(istream& start)
403 :DerByteString(start)
404{}
405
406DerOctetString::~DerOctetString()
407{}
408
409
410/*
411 * DerNull
412 */
413DerNull::DerNull()
414 :DerNode(DER_NULL)
415{
416 DerNode::encodeHeader(0);
417}
418
419DerNull::DerNull(istream& start)
420 :DerNode(start)
421{}
422
423DerNull::~DerNull()
424{}
425
426
427/*
428 * DerOid
429 */
430DerOid::DerOid(const OID& oid)
431 :DerNode(DER_OBJECT_IDENTIFIER)
432{
433 prepareEncoding(oid.getIntegerList());
434}
435
436
437DerOid::DerOid(const string& oidStr)
438 :DerNode(DER_OBJECT_IDENTIFIER)
439{
440 vector<int> value;
441
442 string str = oidStr + ".";
443
444 size_t pos = 0;
445 size_t ppos = 0;
446
447 while(string::npos != pos){
448 ppos = pos;
449
450 pos = str.find_first_of('.', pos);
451 if(string::npos == pos)
452 break;
453
454 value.push_back(atoi(str.substr(ppos, pos - ppos).c_str()));
455
456 pos++;
457 }
458
459 prepareEncoding(value);
460}
461
462DerOid::DerOid(const vector<int>& value)
463 :DerNode(DER_OBJECT_IDENTIFIER)
464{
465 prepareEncoding(value);
466}
467
468DerOid::DerOid(istream& start)
469 :DerNode(start)
470{}
471
472DerOid::~DerOid()
473{}
474
475void
476DerOid::prepareEncoding(const vector<int>& value)
477{
478 ostringstream os;
479
480 int firstNumber = 0;
481
482 if(value.size() >= 1){
483 if(0 <= value[0] && 2 >= value[0])
484 firstNumber = value[0] * 40;
485 else
486 throw DerEncodingException("first integer of oid is out of range");
487 }
488 else
489 throw DerEncodingException("no integer in oid");
490
491 if(value.size() >= 2){
492 if(0 <= value[1] && 39 >= value[1])
493 firstNumber += value[1];
494 else
495 throw DerEncodingException("second integer of oid is out of range");
496 }
497
498 encode128(firstNumber, os);
499
500 if(value.size() > 2){
501 int i = 2;
502 for(; i < value.size(); i++)
503 encode128(value[i], os);
504 }
505
506 string output = os.str();
507 DerNode::encodeHeader(output.size());
508
509 m_payload.insert(m_payload.end(), output.begin(), output.end());
510}
511
512void
513DerOid::encode128(int value, ostringstream& os)
514{
515 int mask = (1 << 7) - 1;
516
517 if(128 > value)
518 {
519 uint8_t singleByte = (uint8_t) mask & value;
520 os.write((char *)&singleByte, 1);
521 }
522 else{
523 uint8_t buf[(sizeof(value)*8 + 6)/7 + 1];
524 uint8_t *p = &(buf[sizeof(buf)-1]);
525 int n = 1;
526
527 p[0] = (uint8_t)(value & mask);
528 value >>= 7;
529
530 while(value != 0)
531 {
532 (--p)[0] = (uint8_t)((value & mask) | (1 << 7));
533 n++;
534 value >>= 7;
535 }
536
537 os.write((char *)p, n);
538 }
539}
540
541int
542DerOid::decode128(int & offset)
543{
544 uint8_t flagMask = 0x80;
545 int result = 0;
546 while(m_payload[offset] & flagMask){
547 result = 128 * result + (uint8_t) m_payload[offset] - 128;
548 offset++;
549 }
550
551 result = result * 128 + m_payload[offset];
552 offset++;
553
554 return result;
555}
556
557
558/*
559 * DerSequence
560 */
561DerSequence::DerSequence()
562 :DerComplex(DER_SEQUENCE)
563{}
564
565DerSequence::DerSequence(istream& start)
566 :DerComplex(start)
567{}
568
569DerSequence::~DerSequence()
570{}
571
572
573/*
574 * DerPrintableString
575 */
576DerPrintableString::DerPrintableString(const string& str)
577 :DerByteString(str, DER_PRINTABLE_STRING)
578{}
579
580DerPrintableString::DerPrintableString(const vector<uint8_t>& blob)
581 :DerByteString(blob, DER_PRINTABLE_STRING)
582{}
583
584DerPrintableString::DerPrintableString(istream& start)
585 :DerByteString(start)
586{}
587
588DerPrintableString::~DerPrintableString()
589{}
590
591
592/*
593 * DerGtime
594 */
595DerGtime::DerGtime(const Time& time)
596 :DerNode(DER_GENERALIZED_TIME)
597{
598 string pTimeStr = toIsoString(time);
599 int index = pTimeStr.find_first_of('T');
600 string derTime = pTimeStr.substr(0, index) + pTimeStr.substr(index+1, pTimeStr.size() - index -1) + "Z";
601 m_payload.insert(m_payload.end(), derTime.begin(), derTime.end());
602
603 DerNode::encodeHeader(m_payload.size());
604}
605
606DerGtime::DerGtime(istream& start)
607 :DerNode(start)
608{}
609
610DerGtime::~DerGtime()
611{}
612
613string DerGtime::toIsoString(const Time& time)
614{
615#if 1
616 throw std::runtime_error("not implemented");
617#endif
618}
619
620Time DerGtime::fromIsoString(const string& isoString)
621{
622#if 1
623 throw std::runtime_error("not implemented");
624#endif
625}
626
627} // der
628
629}