| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 | 
							- var inherits = require('inherits');
 
- var asn1 = require('../../asn1');
 
- var base = asn1.base;
 
- var bignum = asn1.bignum;
 
- // Import DER constants
 
- var der = asn1.constants.der;
 
- function DERDecoder(entity) {
 
-   this.enc = 'der';
 
-   this.name = entity.name;
 
-   this.entity = entity;
 
-   // Construct base tree
 
-   this.tree = new DERNode();
 
-   this.tree._init(entity.body);
 
- };
 
- module.exports = DERDecoder;
 
- DERDecoder.prototype.decode = function decode(data, options) {
 
-   if (!(data instanceof base.DecoderBuffer))
 
-     data = new base.DecoderBuffer(data, options);
 
-   return this.tree._decode(data, options);
 
- };
 
- // Tree methods
 
- function DERNode(parent) {
 
-   base.Node.call(this, 'der', parent);
 
- }
 
- inherits(DERNode, base.Node);
 
- DERNode.prototype._peekTag = function peekTag(buffer, tag, any) {
 
-   if (buffer.isEmpty())
 
-     return false;
 
-   var state = buffer.save();
 
-   var decodedTag = derDecodeTag(buffer, 'Failed to peek tag: "' + tag + '"');
 
-   if (buffer.isError(decodedTag))
 
-     return decodedTag;
 
-   buffer.restore(state);
 
-   return decodedTag.tag === tag || decodedTag.tagStr === tag ||
 
-     (decodedTag.tagStr + 'of') === tag || any;
 
- };
 
- DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) {
 
-   var decodedTag = derDecodeTag(buffer,
 
-                                 'Failed to decode tag of "' + tag + '"');
 
-   if (buffer.isError(decodedTag))
 
-     return decodedTag;
 
-   var len = derDecodeLen(buffer,
 
-                          decodedTag.primitive,
 
-                          'Failed to get length of "' + tag + '"');
 
-   // Failure
 
-   if (buffer.isError(len))
 
-     return len;
 
-   if (!any &&
 
-       decodedTag.tag !== tag &&
 
-       decodedTag.tagStr !== tag &&
 
-       decodedTag.tagStr + 'of' !== tag) {
 
-     return buffer.error('Failed to match tag: "' + tag + '"');
 
-   }
 
-   if (decodedTag.primitive || len !== null)
 
-     return buffer.skip(len, 'Failed to match body of: "' + tag + '"');
 
-   // Indefinite length... find END tag
 
-   var state = buffer.save();
 
-   var res = this._skipUntilEnd(
 
-       buffer,
 
-       'Failed to skip indefinite length body: "' + this.tag + '"');
 
-   if (buffer.isError(res))
 
-     return res;
 
-   len = buffer.offset - state.offset;
 
-   buffer.restore(state);
 
-   return buffer.skip(len, 'Failed to match body of: "' + tag + '"');
 
- };
 
- DERNode.prototype._skipUntilEnd = function skipUntilEnd(buffer, fail) {
 
-   while (true) {
 
-     var tag = derDecodeTag(buffer, fail);
 
-     if (buffer.isError(tag))
 
-       return tag;
 
-     var len = derDecodeLen(buffer, tag.primitive, fail);
 
-     if (buffer.isError(len))
 
-       return len;
 
-     var res;
 
-     if (tag.primitive || len !== null)
 
-       res = buffer.skip(len)
 
-     else
 
-       res = this._skipUntilEnd(buffer, fail);
 
-     // Failure
 
-     if (buffer.isError(res))
 
-       return res;
 
-     if (tag.tagStr === 'end')
 
-       break;
 
-   }
 
- };
 
- DERNode.prototype._decodeList = function decodeList(buffer, tag, decoder,
 
-                                                     options) {
 
-   var result = [];
 
-   while (!buffer.isEmpty()) {
 
-     var possibleEnd = this._peekTag(buffer, 'end');
 
-     if (buffer.isError(possibleEnd))
 
-       return possibleEnd;
 
-     var res = decoder.decode(buffer, 'der', options);
 
-     if (buffer.isError(res) && possibleEnd)
 
-       break;
 
-     result.push(res);
 
-   }
 
-   return result;
 
- };
 
- DERNode.prototype._decodeStr = function decodeStr(buffer, tag) {
 
-   if (tag === 'bitstr') {
 
-     var unused = buffer.readUInt8();
 
-     if (buffer.isError(unused))
 
-       return unused;
 
-     return { unused: unused, data: buffer.raw() };
 
-   } else if (tag === 'bmpstr') {
 
-     var raw = buffer.raw();
 
-     if (raw.length % 2 === 1)
 
-       return buffer.error('Decoding of string type: bmpstr length mismatch');
 
-     var str = '';
 
-     for (var i = 0; i < raw.length / 2; i++) {
 
-       str += String.fromCharCode(raw.readUInt16BE(i * 2));
 
-     }
 
-     return str;
 
-   } else if (tag === 'numstr') {
 
-     var numstr = buffer.raw().toString('ascii');
 
-     if (!this._isNumstr(numstr)) {
 
-       return buffer.error('Decoding of string type: ' +
 
-                           'numstr unsupported characters');
 
-     }
 
-     return numstr;
 
-   } else if (tag === 'octstr') {
 
-     return buffer.raw();
 
-   } else if (tag === 'objDesc') {
 
-     return buffer.raw();
 
-   } else if (tag === 'printstr') {
 
-     var printstr = buffer.raw().toString('ascii');
 
-     if (!this._isPrintstr(printstr)) {
 
-       return buffer.error('Decoding of string type: ' +
 
-                           'printstr unsupported characters');
 
-     }
 
-     return printstr;
 
-   } else if (/str$/.test(tag)) {
 
-     return buffer.raw().toString();
 
-   } else {
 
-     return buffer.error('Decoding of string type: ' + tag + ' unsupported');
 
-   }
 
- };
 
- DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) {
 
-   var result;
 
-   var identifiers = [];
 
-   var ident = 0;
 
-   while (!buffer.isEmpty()) {
 
-     var subident = buffer.readUInt8();
 
-     ident <<= 7;
 
-     ident |= subident & 0x7f;
 
-     if ((subident & 0x80) === 0) {
 
-       identifiers.push(ident);
 
-       ident = 0;
 
-     }
 
-   }
 
-   if (subident & 0x80)
 
-     identifiers.push(ident);
 
-   var first = (identifiers[0] / 40) | 0;
 
-   var second = identifiers[0] % 40;
 
-   if (relative)
 
-     result = identifiers;
 
-   else
 
-     result = [first, second].concat(identifiers.slice(1));
 
-   if (values) {
 
-     var tmp = values[result.join(' ')];
 
-     if (tmp === undefined)
 
-       tmp = values[result.join('.')];
 
-     if (tmp !== undefined)
 
-       result = tmp;
 
-   }
 
-   return result;
 
- };
 
- DERNode.prototype._decodeTime = function decodeTime(buffer, tag) {
 
-   var str = buffer.raw().toString();
 
-   if (tag === 'gentime') {
 
-     var year = str.slice(0, 4) | 0;
 
-     var mon = str.slice(4, 6) | 0;
 
-     var day = str.slice(6, 8) | 0;
 
-     var hour = str.slice(8, 10) | 0;
 
-     var min = str.slice(10, 12) | 0;
 
-     var sec = str.slice(12, 14) | 0;
 
-   } else if (tag === 'utctime') {
 
-     var year = str.slice(0, 2) | 0;
 
-     var mon = str.slice(2, 4) | 0;
 
-     var day = str.slice(4, 6) | 0;
 
-     var hour = str.slice(6, 8) | 0;
 
-     var min = str.slice(8, 10) | 0;
 
-     var sec = str.slice(10, 12) | 0;
 
-     if (year < 70)
 
-       year = 2000 + year;
 
-     else
 
-       year = 1900 + year;
 
-   } else {
 
-     return buffer.error('Decoding ' + tag + ' time is not supported yet');
 
-   }
 
-   return Date.UTC(year, mon - 1, day, hour, min, sec, 0);
 
- };
 
- DERNode.prototype._decodeNull = function decodeNull(buffer) {
 
-   return null;
 
- };
 
- DERNode.prototype._decodeBool = function decodeBool(buffer) {
 
-   var res = buffer.readUInt8();
 
-   if (buffer.isError(res))
 
-     return res;
 
-   else
 
-     return res !== 0;
 
- };
 
- DERNode.prototype._decodeInt = function decodeInt(buffer, values) {
 
-   // Bigint, return as it is (assume big endian)
 
-   var raw = buffer.raw();
 
-   var res = new bignum(raw);
 
-   if (values)
 
-     res = values[res.toString(10)] || res;
 
-   return res;
 
- };
 
- DERNode.prototype._use = function use(entity, obj) {
 
-   if (typeof entity === 'function')
 
-     entity = entity(obj);
 
-   return entity._getDecoder('der').tree;
 
- };
 
- // Utility methods
 
- function derDecodeTag(buf, fail) {
 
-   var tag = buf.readUInt8(fail);
 
-   if (buf.isError(tag))
 
-     return tag;
 
-   var cls = der.tagClass[tag >> 6];
 
-   var primitive = (tag & 0x20) === 0;
 
-   // Multi-octet tag - load
 
-   if ((tag & 0x1f) === 0x1f) {
 
-     var oct = tag;
 
-     tag = 0;
 
-     while ((oct & 0x80) === 0x80) {
 
-       oct = buf.readUInt8(fail);
 
-       if (buf.isError(oct))
 
-         return oct;
 
-       tag <<= 7;
 
-       tag |= oct & 0x7f;
 
-     }
 
-   } else {
 
-     tag &= 0x1f;
 
-   }
 
-   var tagStr = der.tag[tag];
 
-   return {
 
-     cls: cls,
 
-     primitive: primitive,
 
-     tag: tag,
 
-     tagStr: tagStr
 
-   };
 
- }
 
- function derDecodeLen(buf, primitive, fail) {
 
-   var len = buf.readUInt8(fail);
 
-   if (buf.isError(len))
 
-     return len;
 
-   // Indefinite form
 
-   if (!primitive && len === 0x80)
 
-     return null;
 
-   // Definite form
 
-   if ((len & 0x80) === 0) {
 
-     // Short form
 
-     return len;
 
-   }
 
-   // Long form
 
-   var num = len & 0x7f;
 
-   if (num > 4)
 
-     return buf.error('length octect is too long');
 
-   len = 0;
 
-   for (var i = 0; i < num; i++) {
 
-     len <<= 8;
 
-     var j = buf.readUInt8(fail);
 
-     if (buf.isError(j))
 
-       return j;
 
-     len |= j;
 
-   }
 
-   return len;
 
- }
 
 
  |