1 /* asn1ocsp-1.0.3.js (c) 2016 Kenji Urushima | kjur.github.com/jsrsasign/license 2 */ 3 /* 4 * asn1ocsp.js - ASN.1 DER encoder classes for OCSP protocol 5 * 6 * Copyright (c) 2016-2017 Kenji Urushima (kenji.urushima@gmail.com) 7 * 8 * This software is licensed under the terms of the MIT License. 9 * https://kjur.github.io/jsrsasign/license 10 * 11 * The above copyright and license notice shall be 12 * included in all copies or substantial portions of the Software. 13 */ 14 15 /** 16 * @fileOverview 17 * @name asn1ocsp-1.0.js 18 * @author Kenji Urushima kenji.urushima@gmail.com 19 * @version jsrsasign 7.2.1 asn1ocsp 1.0.3 (2017-Jun-03) 20 * @since jsrsasign 6.1.0 21 * @license <a href="https://kjur.github.io/jsrsasign/license/">MIT License</a> 22 */ 23 24 if (typeof KJUR == "undefined" || !KJUR) KJUR = {}; 25 if (typeof KJUR.asn1 == "undefined" || !KJUR.asn1) KJUR.asn1 = {}; 26 27 /** 28 * ASN.1 classes for OCSP protocol<br/> 29 * <p> 30 * This name space provides 31 * <a href="https://tools.ietf.org/html/rfc6960">RFC 6960 32 * Online Certificate Status Protocol (OCSP)</a> ASN.1 request and response generator. 33 * 34 * <h4>FEATURES</h4> 35 * <ul> 36 * <li>easily generate OCSP data</li> 37 * </ul> 38 * 39 * <h4>PROVIDED CLASSES</h4> 40 * <ul> 41 * <li>{@link KJUR.asn1.ocsp.CertID} for ASN.1 class as defined in 42 * <a href="https://tools.ietf.org/html/rfc6960#section-4.1.1">RFC 6960 4.1.1</a>. </li> 43 * <li>{@link KJUR.asn1.ocsp.Request} for ASN.1 class as defined in 44 * <a href="https://tools.ietf.org/html/rfc6960#section-4.1.1">RFC 6960 4.1.1</a>. </li> 45 * <li>{@link KJUR.asn1.ocsp.TBSRequest} for ASN.1 class as defined in 46 * <a href="https://tools.ietf.org/html/rfc6960#section-4.1.1">RFC 6960 4.1.1</a>. </li> 47 * <li>{@link KJUR.asn1.ocsp.OCSPRequest} for ASN.1 class as defined in 48 * <a href="https://tools.ietf.org/html/rfc6960#section-4.1.1">RFC 6960 4.1.1</a>. </li> 49 * <li>{@link KJUR.asn1.ocsp.OCSPUtil} for static utility methods.</li> 50 * </ul> 51 * </p> 52 * @name KJUR.asn1.ocsp 53 * @namespace 54 */ 55 if (typeof KJUR.asn1.ocsp == "undefined" || !KJUR.asn1.ocsp) KJUR.asn1.ocsp = {}; 56 57 KJUR.asn1.ocsp.DEFAULT_HASH = "sha1"; 58 59 /** 60 * ASN.1 CertID class for OCSP<br/> 61 * @name KJUR.asn1.ocsp.CertID 62 * @class ASN.1 CertID class for OCSP 63 * @param {Array} params associative array of parameters 64 * @extends KJUR.asn1.ASN1Object 65 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 66 * @description 67 * CertID ASN.1 class is defined in 68 * <a href="https://tools.ietf.org/html/rfc6960#section-4.1.1">RFC 6960 4.1.1</a>. 69 * <pre> 70 * CertID ::= SEQUENCE { 71 * hashAlgorithm AlgorithmIdentifier, 72 * issuerNameHash OCTET STRING, -- Hash of issuer's DN 73 * issuerKeyHash OCTET STRING, -- Hash of issuer's public key 74 * serialNumber CertificateSerialNumber } 75 * </pre> 76 * @example 77 * // default constructor 78 * o = new KJUR.asn1.ocsp.CertID(); 79 * // constructor with certs (sha1 is used by default) 80 * o = new KJUR.asn1.ocsp.CertID({issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN..."}); 81 * // constructor with certs and sha256 82 * o = new KJUR.asn1.ocsp.CertID({issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg: "sha256"}); 83 * // constructor with values 84 * o = new KJUR.asn1.ocsp.CertID({namehash: "1a...", keyhash: "ad...", serial: "1234", alg: "sha256"}); 85 */ 86 KJUR.asn1.ocsp.CertID = function(params) { 87 var _KJUR = KJUR, 88 _KJUR_asn1 = _KJUR.asn1, 89 _DEROctetString = _KJUR_asn1.DEROctetString, 90 _DERInteger = _KJUR_asn1.DERInteger, 91 _DERSequence = _KJUR_asn1.DERSequence, 92 _KJUR_asn1_x509 = _KJUR_asn1.x509, 93 _AlgorithmIdentifier = _KJUR_asn1_x509.AlgorithmIdentifier, 94 _KJUR_asn1_ocsp = _KJUR_asn1.ocsp, 95 _DEFAULT_HASH = _KJUR_asn1_ocsp.DEFAULT_HASH, 96 _KJUR_crypto = _KJUR.crypto, 97 _hashHex = _KJUR_crypto.Util.hashHex, 98 _X509 = X509, 99 _ASN1HEX = ASN1HEX; 100 101 _KJUR_asn1_ocsp.CertID.superclass.constructor.call(this); 102 103 this.dHashAlg = null; 104 this.dIssuerNameHash = null; 105 this.dIssuerKeyHash = null; 106 this.dSerialNumber = null; 107 108 /** 109 * set CertID ASN.1 object by values.<br/> 110 * @name setByValue 111 * @memberOf KJUR.asn1.ocsp.CertID# 112 * @function 113 * @param {String} issuerNameHashHex hexadecimal string of hash value of issuer name 114 * @param {String} issuerKeyHashHex hexadecimal string of hash value of issuer public key 115 * @param {String} serialNumberHex hexadecimal string of certificate serial number to be verified 116 * @param {String} algName hash algorithm name used for above arguments (ex. "sha1") DEFAULT: sha1 117 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 118 * @example 119 * o = new KJUR.asn1.ocsp.CertID(); 120 * o.setByValue("1fac...", "fd3a...", "1234"); // sha1 is used by default 121 * o.setByValue("1fac...", "fd3a...", "1234", "sha256"); 122 */ 123 this.setByValue = function(issuerNameHashHex, issuerKeyHashHex, 124 serialNumberHex, algName) { 125 if (algName === undefined) algName = _DEFAULT_HASH; 126 this.dHashAlg = new _AlgorithmIdentifier({name: algName}); 127 this.dIssuerNameHash = new _DEROctetString({hex: issuerNameHashHex}); 128 this.dIssuerKeyHash = new _DEROctetString({hex: issuerKeyHashHex}); 129 this.dSerialNumber = new _DERInteger({hex: serialNumberHex}); 130 }; 131 132 /** 133 * set CertID ASN.1 object by PEM certificates.<br/> 134 * @name setByCert 135 * @memberOf KJUR.asn1.ocsp.CertID# 136 * @function 137 * @param {String} issuerCert string of PEM issuer certificate 138 * @param {String} subjectCert string of PEM subject certificate to be verified by OCSP 139 * @param {String} algName hash algorithm name used for above arguments (ex. "sha1") DEFAULT: sha1 140 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 141 * @example 142 * o = new KJUR.asn1.ocsp.CertID(); 143 * o.setByCert("-----BEGIN...", "-----BEGIN..."); // sha1 is used by default 144 * o.setByCert("-----BEGIN...", "-----BEGIN...", "sha256"); 145 */ 146 this.setByCert = function(issuerCert, subjectCert, algName) { 147 if (algName === undefined) algName = _DEFAULT_HASH; 148 149 var xSbj = new _X509(); 150 xSbj.readCertPEM(subjectCert); 151 var xIss = new _X509(); 152 xIss.readCertPEM(issuerCert); 153 154 var hISS_SPKI = xIss.getPublicKeyHex(); 155 var issuerKeyHex = _ASN1HEX.getTLVbyList(hISS_SPKI, 0, [1, 0], "30"); 156 157 var serialNumberHex = xSbj.getSerialNumberHex(); 158 var issuerNameHashHex = _hashHex(xIss.getSubjectHex(), algName); 159 var issuerKeyHashHex = _hashHex(issuerKeyHex, algName); 160 this.setByValue(issuerNameHashHex, issuerKeyHashHex, 161 serialNumberHex, algName); 162 this.hoge = xSbj.getSerialNumberHex(); 163 }; 164 165 this.getEncodedHex = function() { 166 if (this.dHashAlg === null && 167 this.dIssuerNameHash === null && 168 this.dIssuerKeyHash === null && 169 this.dSerialNumber === null) 170 throw "not yet set values"; 171 172 var a = [this.dHashAlg, this.dIssuerNameHash, 173 this.dIssuerKeyHash, this.dSerialNumber]; 174 var seq = new _DERSequence({array: a}); 175 this.hTLV = seq.getEncodedHex(); 176 return this.hTLV; 177 }; 178 179 if (params !== undefined) { 180 var p = params; 181 if (p.issuerCert !== undefined && 182 p.subjectCert !== undefined) { 183 var alg = _DEFAULT_HASH; 184 if (p.alg === undefined) alg = undefined; 185 this.setByCert(p.issuerCert, p.subjectCert, alg); 186 } else if (p.namehash !== undefined && 187 p.keyhash !== undefined && 188 p.serial !== undefined) { 189 var alg = _DEFAULT_HASH; 190 if (p.alg === undefined) alg = undefined; 191 this.setByValue(p.namehash, p.keyhash, p.serial, alg); 192 } else { 193 throw "invalid constructor arguments"; 194 } 195 } 196 }; 197 YAHOO.lang.extend(KJUR.asn1.ocsp.CertID, KJUR.asn1.ASN1Object); 198 199 /** 200 * ASN.1 Request class for OCSP<br/> 201 * @name KJUR.asn1.ocsp.Request 202 * @class ASN.1 Request class for OCSP 203 * @param {Array} params associative array of parameters 204 * @extends KJUR.asn1.ASN1Object 205 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 206 * @description 207 * Request ASN.1 class is defined in 208 * <a href="https://tools.ietf.org/html/rfc6960#section-4.1.1">RFC 6960 4.1.1</a>. 209 * singleRequestExtensions is not supported yet in this version such as nonce. 210 * <pre> 211 * Request ::= SEQUENCE { 212 * reqCert CertID, 213 * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } 214 * </pre> 215 * @example 216 * // default constructor 217 * o = new KJUR.asn1.ocsp.Request(); 218 * // constructor with certs (sha1 is used by default) 219 * o = new KJUR.asn1.ocsp.Request({issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN..."}); 220 * // constructor with certs and sha256 221 * o = new KJUR.asn1.ocsp.Request({issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg: "sha256"}); 222 * // constructor with values 223 * o = new KJUR.asn1.ocsp.Request({namehash: "1a...", keyhash: "ad...", serial: "1234", alg: "sha256"}); 224 */ 225 KJUR.asn1.ocsp.Request = function(params) { 226 var _KJUR = KJUR, 227 _KJUR_asn1 = _KJUR.asn1, 228 _DERSequence = _KJUR_asn1.DERSequence, 229 _KJUR_asn1_ocsp = _KJUR_asn1.ocsp; 230 231 _KJUR_asn1_ocsp.Request.superclass.constructor.call(this); 232 this.dReqCert = null; 233 this.dExt = null; 234 235 this.getEncodedHex = function() { 236 var a = []; 237 238 // 1. reqCert 239 if (this.dReqCert === null) 240 throw "reqCert not set"; 241 a.push(this.dReqCert); 242 243 // 2. singleRequestExtensions (not supported yet) 244 245 // 3. construct SEQUENCE 246 var seq = new _DERSequence({array: a}); 247 this.hTLV = seq.getEncodedHex(); 248 return this.hTLV; 249 }; 250 251 if (typeof params !== "undefined") { 252 var o = new _KJUR_asn1_ocsp.CertID(params); 253 this.dReqCert = o; 254 } 255 }; 256 YAHOO.lang.extend(KJUR.asn1.ocsp.Request, KJUR.asn1.ASN1Object); 257 258 /** 259 * ASN.1 TBSRequest class for OCSP<br/> 260 * @name KJUR.asn1.ocsp.TBSRequest 261 * @class ASN.1 TBSRequest class for OCSP 262 * @param {Array} params associative array of parameters 263 * @extends KJUR.asn1.ASN1Object 264 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 265 * @description 266 * TBSRequest ASN.1 class is defined in 267 * <a href="https://tools.ietf.org/html/rfc6960#section-4.1.1">RFC 6960 4.1.1</a>. 268 * <pre> 269 * TBSRequest ::= SEQUENCE { 270 * version [0] EXPLICIT Version DEFAULT v1, 271 * requestorName [1] EXPLICIT GeneralName OPTIONAL, 272 * requestList SEQUENCE OF Request, 273 * requestExtensions [2] EXPLICIT Extensions OPTIONAL } 274 * </pre> 275 * @example 276 * // default constructor 277 * o = new KJUR.asn1.ocsp.TBSRequest(); 278 * // constructor with requestList parameter 279 * o = new KJUR.asn1.ocsp.TBSRequest({reqList:[ 280 * {issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg:}, 281 * {issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg: "sha256"} 282 * ]}); 283 */ 284 KJUR.asn1.ocsp.TBSRequest = function(params) { 285 var _KJUR = KJUR, 286 _KJUR_asn1 = _KJUR.asn1, 287 _DERSequence = _KJUR_asn1.DERSequence, 288 _KJUR_asn1_ocsp = _KJUR_asn1.ocsp; 289 290 _KJUR_asn1_ocsp.TBSRequest.superclass.constructor.call(this); 291 this.version = 0; 292 this.dRequestorName = null; 293 this.dRequestList = []; 294 this.dRequestExt = null; 295 296 /** 297 * set TBSRequest ASN.1 object by array of parameters.<br/> 298 * @name setRequestListByParam 299 * @memberOf KJUR.asn1.ocsp.TBSRequest# 300 * @function 301 * @param {Array} aParams array of parameters for Request class 302 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 303 * @example 304 * o = new KJUR.asn1.ocsp.TBSRequest(); 305 * o.setRequestListByParam([ 306 * {issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg:}, 307 * {issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg: "sha256"} 308 * ]); 309 */ 310 this.setRequestListByParam = function(aParams) { 311 var a = []; 312 for (var i = 0; i < aParams.length; i++) { 313 var dReq = new _KJUR_asn1_ocsp.Request(aParams[0]); 314 a.push(dReq); 315 } 316 this.dRequestList = a; 317 }; 318 319 this.getEncodedHex = function() { 320 var a = []; 321 322 // 1. version 323 if (this.version !== 0) 324 throw "not supported version: " + this.version; 325 326 // 2. requestorName 327 if (this.dRequestorName !== null) 328 throw "requestorName not supported"; 329 330 // 3. requestList 331 var seqRequestList = 332 new _DERSequence({array: this.dRequestList}); 333 a.push(seqRequestList); 334 335 // 4. requestExtensions 336 if (this.dRequestExt !== null) 337 throw "requestExtensions not supported"; 338 339 // 5. construct SEQUENCE 340 var seq = new _DERSequence({array: a}); 341 this.hTLV = seq.getEncodedHex(); 342 return this.hTLV; 343 }; 344 345 if (params !== undefined) { 346 if (params.reqList !== undefined) 347 this.setRequestListByParam(params.reqList); 348 } 349 }; 350 YAHOO.lang.extend(KJUR.asn1.ocsp.TBSRequest, KJUR.asn1.ASN1Object); 351 352 353 /** 354 * ASN.1 OCSPRequest class for OCSP<br/> 355 * @name KJUR.asn1.ocsp.OCSPRequest 356 * @class ASN.1 OCSPRequest class for OCSP 357 * @param {Array} params associative array of parameters 358 * @extends KJUR.asn1.ASN1Object 359 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 360 * @description 361 * OCSPRequest ASN.1 class is defined in 362 * <a href="https://tools.ietf.org/html/rfc6960#section-4.1.1">RFC 6960 4.1.1</a>. 363 * A signed request is not supported yet in this version. 364 * <pre> 365 * OCSPRequest ::= SEQUENCE { 366 * tbsRequest TBSRequest, 367 * optionalSignature [0] EXPLICIT Signature OPTIONAL } 368 * </pre> 369 * @example 370 * // default constructor 371 * o = new KJUR.asn1.ocsp.OCSPRequest(); 372 * // constructor with requestList parameter 373 * o = new KJUR.asn1.ocsp.OCSPRequest({reqList:[ 374 * {issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg:}, 375 * {issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg: "sha256"} 376 * ]}); 377 */ 378 KJUR.asn1.ocsp.OCSPRequest = function(params) { 379 var _KJUR = KJUR, 380 _KJUR_asn1 = _KJUR.asn1, 381 _DERSequence = _KJUR_asn1.DERSequence, 382 _KJUR_asn1_ocsp = _KJUR_asn1.ocsp; 383 384 _KJUR_asn1_ocsp.OCSPRequest.superclass.constructor.call(this); 385 this.dTbsRequest = null; 386 this.dOptionalSignature = null; 387 388 this.getEncodedHex = function() { 389 var a = []; 390 391 // 1. tbsRequest 392 if (this.dTbsRequest !== null) { 393 a.push(this.dTbsRequest); 394 } else { 395 throw "tbsRequest not set"; 396 } 397 398 // 2. optionalSignature 399 if (this.dOptionalSignature !== null) 400 throw "optionalSignature not supported"; 401 402 // 3. construct SEQUENCE 403 var seq = new _DERSequence({array: a}); 404 this.hTLV = seq.getEncodedHex(); 405 return this.hTLV; 406 }; 407 408 if (params !== undefined) { 409 if (params.reqList !== undefined) { 410 var o = new _KJUR_asn1_ocsp.TBSRequest(params); 411 this.dTbsRequest = o; 412 } 413 } 414 }; 415 YAHOO.lang.extend(KJUR.asn1.ocsp.OCSPRequest, KJUR.asn1.ASN1Object); 416 417 /** 418 * Utility class for OCSP<br/> 419 * @name KJUR.asn1.ocsp.OCSPUtil 420 * @class Utility class for OCSP 421 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 422 * @description 423 * This class provides utility static methods for OCSP. 424 * <ul> 425 * <li>{@link KJUR.asn1.ocsp.OCSPUtil.getRequestHex} - generates hexadecimal string of OCSP request</li> 426 * </ul> 427 */ 428 KJUR.asn1.ocsp.OCSPUtil = {}; 429 430 /** 431 * generates hexadecimal string of OCSP request<br/> 432 * @name getRequestHex 433 * @memberOf KJUR.asn1.ocsp.OCSPUtil 434 * @function 435 * @param {String} issuerCert string of PEM issuer certificate 436 * @param {String} subjectCert string of PEM subject certificate to be verified by OCSP 437 * @param {String} algName hash algorithm name used for above arguments (ex. "sha1") DEFAULT: sha1 438 * @return {String} hexadecimal string of generated OCSP request 439 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 440 * @description 441 * This static method generates hexadecimal string of OCSP request. 442 * @example 443 * // generate OCSP request using sha1 algorithnm by default. 444 * hReq = KJUR.asn1.ocsp.OCSPUtil.getRequestHex("-----BEGIN...", "-----BEGIN..."); 445 */ 446 KJUR.asn1.ocsp.OCSPUtil.getRequestHex = function(issuerCert, subjectCert, alg) { 447 var _KJUR = KJUR, 448 _KJUR_asn1 = _KJUR.asn1, 449 _KJUR_asn1_ocsp = _KJUR_asn1.ocsp; 450 451 if (alg === undefined) alg = _KJUR_asn1_ocsp.DEFAULT_HASH; 452 var param = {alg: alg, issuerCert: issuerCert, subjectCert: subjectCert}; 453 var o = new _KJUR_asn1_ocsp.OCSPRequest({reqList: [param]}); 454 return o.getEncodedHex(); 455 }; 456 457 /** 458 * parse OCSPResponse<br/> 459 * @name getOCSPResponseInfo 460 * @memberOf KJUR.asn1.ocsp.OCSPUtil 461 * @function 462 * @param {String} h hexadecimal string of DER OCSPResponse 463 * @return {Object} JSON object of parsed OCSPResponse 464 * @since jsrsasign 6.1.0 asn1ocsp 1.0.1 465 * @description 466 * This static method parse a hexadecimal string of DER OCSPResponse and 467 * returns JSON object of its parsed result. 468 * Its result has following properties: 469 * <ul> 470 * <li>responseStatus - integer of responseStatus</li> 471 * <li>certStatus - string of certStatus (ex. good, revoked or unknown)</li> 472 * <li>thisUpdate - string of thisUpdate in Zulu(ex. 20151231235959Z)</li> 473 * <li>nextUpdate - string of nextUpdate in Zulu(ex. 20151231235959Z)</li> 474 * </ul> 475 * @example 476 * info = KJUR.asn1.ocsp.OCSPUtil.getOCSPResponseInfo("3082..."); 477 */ 478 KJUR.asn1.ocsp.OCSPUtil.getOCSPResponseInfo = function(h) { 479 var _ASN1HEX = ASN1HEX; 480 var _getVbyList = _ASN1HEX.getVbyList; 481 var _getIdxbyList = _ASN1HEX.getIdxbyList; 482 var _getVbyList = _ASN1HEX.getVbyList; 483 var _getV = _ASN1HEX.getV; 484 485 var result = {}; 486 try { 487 var v = _getVbyList(h, 0, [0], "0a"); 488 result.responseStatus = parseInt(v, 16); 489 } catch(ex) {}; 490 if (result.responseStatus !== 0) return result; 491 492 try { 493 // certStatus 494 var idxCertStatus = _getIdxbyList(h, 0, [1,0,1,0,0,2,0,1]); 495 if (h.substr(idxCertStatus, 2) === "80") { 496 result.certStatus = "good"; 497 } else if (h.substr(idxCertStatus, 2) === "a1") { 498 result.certStatus = "revoked"; 499 result.revocationTime = 500 hextoutf8(_getVbyList(h, idxCertStatus, [0])); 501 } else if (h.substr(idxCertStatus, 2) === "82") { 502 result.certStatus = "unknown"; 503 } 504 } catch (ex) {}; 505 506 // thisUpdate 507 try { 508 var idxThisUpdate = _getIdxbyList(h, 0, [1,0,1,0,0,2,0,2]); 509 result.thisUpdate = hextoutf8(_getV(h, idxThisUpdate)); 510 } catch (ex) {}; 511 512 // nextUpdate 513 try { 514 var idxEncapNextUpdate = _getIdxbyList(h, 0, [1,0,1,0,0,2,0,3]); 515 if (h.substr(idxEncapNextUpdate, 2) === "a0") { 516 result.nextUpdate = 517 hextoutf8(_getVbyList(h, idxEncapNextUpdate, [0])); 518 } 519 } catch (ex) {}; 520 521 return result; 522 }; 523 524