node-forge 1.3.1 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/aes.js CHANGED
@@ -325,7 +325,7 @@ var imix; // inverse mix-columns table
325
325
  * The word [a0, a1, a2, a3] is a polynomial a3x^3 + a2x^2 + a1x + a0.
326
326
  *
327
327
  * Addition is performed by XOR'ing like powers of x. Multiplication
328
- * is performed in two steps, the first is an algebriac expansion as
328
+ * is performed in two steps, the first is an algebraic expansion as
329
329
  * you would do normally (where addition is XOR). But the result is
330
330
  * a polynomial larger than 3 degrees and thus it cannot fit in a word. So
331
331
  * next the result is modularly reduced by an AES-specific polynomial of
package/lib/asn1.js CHANGED
@@ -178,6 +178,11 @@ asn1.Type = {
178
178
  BMPSTRING: 30
179
179
  };
180
180
 
181
+ /**
182
+ * Sets the default maximum recursion depth when parsing ASN.1 structures.
183
+ */
184
+ asn1.maxDepth = 256;
185
+
181
186
  /**
182
187
  * Creates a new asn1 object.
183
188
  *
@@ -419,6 +424,8 @@ var _getValueLength = function(bytes, remaining) {
419
424
  * erroneously decode values that happen to be valid ASN.1. This
420
425
  * flag will be deprecated or removed as soon as schema support is
421
426
  * available. (default: true)
427
+ * [maxDepth] override asn1.maxDepth recursion limit
428
+ * (default: asn1.maxDepth)
422
429
  *
423
430
  * @throws Will throw an error for various malformed input conditions.
424
431
  *
@@ -448,6 +455,9 @@ asn1.fromDer = function(bytes, options) {
448
455
  if(!('decodeBitStrings' in options)) {
449
456
  options.decodeBitStrings = true;
450
457
  }
458
+ if(!('maxDepth' in options)) {
459
+ options.maxDepth = asn1.maxDepth;
460
+ }
451
461
 
452
462
  // wrap in buffer if needed
453
463
  if(typeof bytes === 'string') {
@@ -476,6 +486,12 @@ asn1.fromDer = function(bytes, options) {
476
486
  * @return the parsed asn1 object.
477
487
  */
478
488
  function _fromDer(bytes, remaining, depth, options) {
489
+
490
+ // check depth limit
491
+ if(depth >= options.maxDepth) {
492
+ throw new Error('ASN.1 parsing error: Max depth exceeded.');
493
+ }
494
+
479
495
  // temporary storage for consumption calculations
480
496
  var start;
481
497
 
@@ -773,6 +789,10 @@ asn1.oidToDer = function(oid) {
773
789
  last = true;
774
790
  valueBytes = [];
775
791
  value = parseInt(values[i], 10);
792
+ // TODO: Change bitwise logic to allow larger values.
793
+ if(value > 0xffffffff) {
794
+ throw new Error('OID value too large; max is 32-bits.');
795
+ }
776
796
  do {
777
797
  b = value & 0x7F;
778
798
  value = value >>> 7;
@@ -818,8 +838,13 @@ asn1.derToOid = function(bytes) {
818
838
  // the last byte for each value
819
839
  var value = 0;
820
840
  while(bytes.length() > 0) {
841
+ // error if 7b shift would exceed Number.MAX_SAFE_INTEGER
842
+ // (Number.MAX_SAFE_INTEGER / 128)
843
+ if(value > 0x3fffffffffff) {
844
+ throw new Error('OID value too large; max is 53-bits.');
845
+ }
821
846
  b = bytes.getByte();
822
- value = value << 7;
847
+ value = value * 128;
823
848
  // not the last byte for the value
824
849
  if(b & 0x80) {
825
850
  value += b & 0x7F;
@@ -1165,22 +1190,65 @@ asn1.validate = function(obj, v, capture, errors) {
1165
1190
  if(v.value && forge.util.isArray(v.value)) {
1166
1191
  var j = 0;
1167
1192
  for(var i = 0; rval && i < v.value.length; ++i) {
1168
- rval = v.value[i].optional || false;
1169
- if(obj.value[j]) {
1170
- rval = asn1.validate(obj.value[j], v.value[i], capture, errors);
1171
- if(rval) {
1172
- ++j;
1173
- } else if(v.value[i].optional) {
1193
+ var schemaItem = v.value[i];
1194
+ rval = !!schemaItem.optional;
1195
+
1196
+ // current child in the object
1197
+ var objChild = obj.value[j];
1198
+
1199
+ // if there is no child left to match
1200
+ if(!objChild) {
1201
+ // if optional, ok (rval already true), else fail below
1202
+ if(!schemaItem.optional) {
1203
+ rval = false;
1204
+ if(errors) {
1205
+ errors.push('[' + v.name + '] ' +
1206
+ 'Missing required element. Expected tag class "' +
1207
+ schemaItem.tagClass + '", type "' + schemaItem.type + '"');
1208
+ }
1209
+ }
1210
+ continue;
1211
+ }
1212
+
1213
+ // If schema explicitly specifies tagClass/type, do a quick structural check
1214
+ // to avoid unnecessary recursion/side-effects when tags clearly don't match.
1215
+ var schemaHasTag = (typeof schemaItem.tagClass !== 'undefined' &&
1216
+ typeof schemaItem.type !== 'undefined');
1217
+
1218
+ if(schemaHasTag &&
1219
+ (objChild.tagClass !== schemaItem.tagClass || objChild.type !== schemaItem.type)) {
1220
+ // Tags do not match.
1221
+ if(schemaItem.optional) {
1222
+ // Skip this schema element (don't consume objChild; don't call recursive validate).
1174
1223
  rval = true;
1224
+ continue;
1225
+ } else {
1226
+ // Required schema item mismatched - fail.
1227
+ rval = false;
1228
+ if(errors) {
1229
+ errors.push('[' + v.name + '] ' +
1230
+ 'Tag mismatch. Expected (' +
1231
+ schemaItem.tagClass + ',' + schemaItem.type + '), got (' +
1232
+ objChild.tagClass + ',' + objChild.type + ')');
1233
+ }
1234
+ break;
1175
1235
  }
1176
1236
  }
1177
- if(!rval && errors) {
1178
- errors.push(
1179
- '[' + v.name + '] ' +
1180
- 'Tag class "' + v.tagClass + '", type "' +
1181
- v.type + '" expected value length "' +
1182
- v.value.length + '", got "' +
1183
- obj.value.length + '"');
1237
+
1238
+ // Tags are compatible (or schema did not declare tags) - dive into recursive validate.
1239
+ var childRval = asn1.validate(objChild, schemaItem, capture, errors);
1240
+ if(childRval) {
1241
+ // consume this child
1242
+ ++j;
1243
+ rval = true;
1244
+ } else if(schemaItem.optional) {
1245
+ // validation failed but element is optional => skip schema item (don't consume child)
1246
+ rval = true;
1247
+ } else {
1248
+ // required item failed
1249
+ rval = false;
1250
+ // errors should already be populated by recursive call; keep failing
1251
+ break;
1184
1252
  }
1185
1253
  }
1186
1254
  }
@@ -1226,7 +1294,8 @@ asn1.validate = function(obj, v, capture, errors) {
1226
1294
  if(obj.type !== v.type) {
1227
1295
  errors.push(
1228
1296
  '[' + v.name + '] ' +
1229
- 'Expected type "' + v.type + '", got "' + obj.type + '"');
1297
+ 'Expected type "' + v.type + '", got "' +
1298
+ obj.type + '"');
1230
1299
  }
1231
1300
  }
1232
1301
  return rval;
package/lib/pbe.js CHANGED
@@ -672,7 +672,7 @@ pki.pbe.generatePkcs12Key = function(password, salt, id, iter, n, md) {
672
672
  D.fillWithByte(id, v);
673
673
 
674
674
  /* 2. Concatenate copies of the salt together to create a string S of length
675
- v * ceil(s / v) bytes (the final copy of the salt may be trunacted
675
+ v * ceil(s / v) bytes (the final copy of the salt may be truncated
676
676
  to create S).
677
677
  Note that if the salt is the empty string, then so is S. */
678
678
  var Slen = v * Math.ceil(s / v);
package/lib/pkcs12.js CHANGED
@@ -168,6 +168,7 @@ var pfxValidator = {
168
168
  capture: 'macAlgorithm'
169
169
  }, {
170
170
  name: 'PFX.macData.mac.digestAlgorithm.parameters',
171
+ optional: true,
171
172
  tagClass: asn1.Class.UNIVERSAL,
172
173
  captureAsn1: 'macAlgorithmParameters'
173
174
  }]
@@ -474,6 +475,9 @@ p12.pkcs12FromAsn1 = function(obj, strict, password) {
474
475
  if(macValue.getBytes() !== capture.macDigest) {
475
476
  throw new Error('PKCS#12 MAC could not be verified. Invalid password?');
476
477
  }
478
+ } else if(Array.isArray(obj.value) && obj.value.length > 2) {
479
+ /* This is pfx data that should have mac and verify macDigest */
480
+ throw new Error('Invalid PKCS#12. macData field present but MAC was not validated.');
477
481
  }
478
482
 
479
483
  _decodeAuthenticatedSafe(pfx, data.value, strict, password);
@@ -56,7 +56,7 @@ function findPrime(data) {
56
56
  }
57
57
 
58
58
  function isProbablePrime(n) {
59
- // divide by low primes, ignore even checks, etc (n alread aligned properly)
59
+ // divide by low primes, ignore even checks, etc (n already aligned properly)
60
60
  var i = 1;
61
61
  while(i < LOW_PRIMES.length) {
62
62
  var m = LOW_PRIMES[i];
package/lib/rsa.js CHANGED
@@ -282,7 +282,7 @@ var digestInfoValidator = {
282
282
  constructed: false,
283
283
  capture: 'algorithmIdentifier'
284
284
  }, {
285
- // NULL paramters
285
+ // NULL parameters
286
286
  name: 'DigestInfo.DigestAlgorithm.parameters',
287
287
  tagClass: asn1.Class.UNIVERSAL,
288
288
  type: asn1.Type.NULL,
@@ -316,7 +316,7 @@ var digestInfoValidator = {
316
316
  *
317
317
  * @param md the message digest object with the hash to sign.
318
318
  *
319
- * @return the encoded message (ready for RSA encrytion)
319
+ * @return the encoded message (ready for RSA encryption)
320
320
  */
321
321
  var emsaPkcs1v15encode = function(md) {
322
322
  // get the oid for the algorithm
@@ -498,7 +498,7 @@ var _modPow = function(x, key, pub) {
498
498
  *
499
499
  * The parameter bt controls whether to put padding bytes before the
500
500
  * message passed in. Set bt to either true or false to disable padding
501
- * completely (in order to handle e.g. EMSA-PSS encoding seperately before),
501
+ * completely (in order to handle e.g. EMSA-PSS encoding separately before),
502
502
  * signaling whether the encryption operation is a public key operation
503
503
  * (i.e. encrypting data) or not, i.e. private key operation (data signing).
504
504
  *
@@ -1173,7 +1173,7 @@ pki.setRsaPublicKey = pki.rsa.setPublicKey = function(n, e) {
1173
1173
  }
1174
1174
  // check hash algorithm identifier
1175
1175
  // see PKCS1-v1-5DigestAlgorithms in RFC 8017
1176
- // FIXME: add support to vaidator for strict value choices
1176
+ // FIXME: add support to validator for strict value choices
1177
1177
  var oid = asn1.derToOid(capture.algorithmIdentifier);
1178
1178
  if(!(oid === forge.oids.md2 ||
1179
1179
  oid === forge.oids.md5 ||
@@ -1196,7 +1196,7 @@ pki.setRsaPublicKey = pki.rsa.setPublicKey = function(n, e) {
1196
1196
  throw new Error(
1197
1197
  'ASN.1 object does not contain a valid RSASSA-PKCS1-v1_5 ' +
1198
1198
  'DigestInfo value. ' +
1199
- 'Missing algorithm identifer NULL parameters.');
1199
+ 'Missing algorithm identifier NULL parameters.');
1200
1200
  }
1201
1201
  }
1202
1202
 
@@ -1637,7 +1637,7 @@ function _decodePkcs1_v1_5(em, key, pub, ml) {
1637
1637
 
1638
1638
  1. The encryption block EB cannot be parsed unambiguously.
1639
1639
  2. The padding string PS consists of fewer than eight octets
1640
- or is inconsisent with the block type BT.
1640
+ or is inconsistent with the block type BT.
1641
1641
  3. The decryption process is a public-key operation and the block
1642
1642
  type BT is not 00 or 01, or the decryption process is a
1643
1643
  private-key operation and the block type is not 02.
package/lib/tls.js CHANGED
@@ -758,7 +758,7 @@ tls.handleUnexpected = function(c, record) {
758
758
  */
759
759
  tls.handleHelloRequest = function(c, record, length) {
760
760
  // ignore renegotiation requests from the server during a handshake, but
761
- // if handshaking, send a warning alert that renegotation is denied
761
+ // if handshaking, send a warning alert that renegotiation is denied
762
762
  if(!c.handshaking && c.handshakes > 0) {
763
763
  // send alert warning
764
764
  tls.queue(c, tls.createAlert(c, {
@@ -2258,7 +2258,7 @@ hsTable[tls.ConnectionEnd.client] = [
2258
2258
  ];
2259
2259
 
2260
2260
  // map server current expect state and handshake type to function
2261
- // Note: CAD[CH] does not map to FB because renegotation is prohibited
2261
+ // Note: CAD[CH] does not map to FB because renegotiation is prohibited
2262
2262
  var H7 = tls.handleClientHello;
2263
2263
  var H8 = tls.handleClientKeyExchange;
2264
2264
  var H9 = tls.handleCertificateVerify;
package/lib/util.js CHANGED
@@ -677,7 +677,7 @@ util.ByteStringBuffer.prototype.clear = function() {
677
677
  };
678
678
 
679
679
  /**
680
- * Shortens this buffer by triming bytes off of the end of this buffer.
680
+ * Shortens this buffer by trimming bytes off of the end of this buffer.
681
681
  *
682
682
  * @param count the number of bytes to trim off.
683
683
  *
@@ -1343,7 +1343,7 @@ util.DataBuffer.prototype.clear = function() {
1343
1343
  };
1344
1344
 
1345
1345
  /**
1346
- * Shortens this buffer by triming bytes off of the end of this buffer.
1346
+ * Shortens this buffer by trimming bytes off of the end of this buffer.
1347
1347
  *
1348
1348
  * @param count the number of bytes to trim off.
1349
1349
  *
@@ -2316,7 +2316,7 @@ util.format = function(format) {
2316
2316
  parts.push('<?>');
2317
2317
  }
2318
2318
  break;
2319
- // FIXME: do proper formating for numbers, etc
2319
+ // FIXME: do proper formatting for numbers, etc
2320
2320
  //case 'f':
2321
2321
  //case 'd':
2322
2322
  case '%':
package/lib/x509.js CHANGED
@@ -2289,7 +2289,7 @@ function _fillMissingExtensionFields(e, options) {
2289
2289
  * Convert signature parameters object to ASN.1
2290
2290
  *
2291
2291
  * @param {String} oid Signature algorithm OID
2292
- * @param params The signature parametrs object
2292
+ * @param params The signature parameters object
2293
2293
  * @return ASN.1 object representing signature parameters
2294
2294
  */
2295
2295
  function _signatureParametersToAsn1(oid, params) {
package/lib/xhr.js CHANGED
@@ -459,7 +459,7 @@ xhrApi.create = function(options) {
459
459
  // set request method to given method
460
460
  // set request URL
461
461
  // set username, password
462
- // set asychronous flag
462
+ // set asynchronous flag
463
463
  _state.sendFlag = false;
464
464
  xhr.responseText = '';
465
465
  xhr.responseXML = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-forge",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "description": "JavaScript implementations of network transports, cryptography, ciphers, PKI, message digests, and various utilities.",
5
5
  "homepage": "https://github.com/digitalbazaar/forge",
6
6
  "author": {