1 /*! asn1ocsp-1.0.1.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 Kenji Urushima (kenji.urushima@gmail.com) 7 * 8 * This software is licensed under the terms of the MIT License. 9 * http://kjur.github.com/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 1.0.1 (2016-Oct-02) 20 * @since jsrsasign 6.1.0 21 * @license <a href="http://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 KJUR.asn1.ocsp.CertID.superclass.constructor.call(this); 88 var nA = KJUR.asn1; 89 var nX = KJUR.asn1.x509; 90 this.dHashAlg = null; 91 this.dIssuerNameHash = null; 92 this.dIssuerKeyHash = null; 93 this.dSerialNumber = null; 94 95 /** 96 * set CertID ASN.1 object by values.<br/> 97 * @name setByValue 98 * @memberOf KJUR.asn1.ocsp.CertID# 99 * @function 100 * @param {String} issuerNameHashHex hexadecimal string of hash value of issuer name 101 * @param {String} issuerKeyHashHex hexadecimal string of hash value of issuer public key 102 * @param {String} serialNumberHex hexadecimal string of certificate serial number to be verified 103 * @param {String} algName hash algorithm name used for above arguments (ex. "sha1") DEFAULT: sha1 104 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 105 * @example 106 * o = new KJUR.asn1.ocsp.CertID(); 107 * o.setByValue("1fac...", "fd3a...", "1234"); // sha1 is used by default 108 * o.setByValue("1fac...", "fd3a...", "1234", "sha256"); 109 */ 110 this.setByValue = function(issuerNameHashHex, issuerKeyHashHex, 111 serialNumberHex, algName) { 112 if (algName === undefined) 113 algName = KJUR.asn1.ocsp.DEFAULT_HASH; 114 this.dHashAlg = new nX.AlgorithmIdentifier({name: algName}); 115 this.dIssuerNameHash = new nA.DEROctetString({hex: issuerNameHashHex}); 116 this.dIssuerKeyHash = new nA.DEROctetString({hex: issuerKeyHashHex}); 117 this.dSerialNumber = new nA.DERInteger({hex: serialNumberHex}); 118 }; 119 120 /** 121 * set CertID ASN.1 object by PEM certificates.<br/> 122 * @name setByCert 123 * @memberOf KJUR.asn1.ocsp.CertID# 124 * @function 125 * @param {String} issuerCert string of PEM issuer certificate 126 * @param {String} subjectCert string of PEM subject certificate to be verified by OCSP 127 * @param {String} algName hash algorithm name used for above arguments (ex. "sha1") DEFAULT: sha1 128 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 129 * @example 130 * o = new KJUR.asn1.ocsp.CertID(); 131 * o.setByCert("-----BEGIN...", "-----BEGIN..."); // sha1 is used by default 132 * o.setByCert("-----BEGIN...", "-----BEGIN...", "sha256"); 133 */ 134 this.setByCert = function(issuerCert, subjectCert, algName) { 135 if (algName === undefined) 136 algName = KJUR.asn1.ocsp.DEFAULT_HASH; 137 138 var xSbj = new X509(); 139 xSbj.readCertPEM(subjectCert); 140 var xIss = new X509(); 141 xIss.readCertPEM(issuerCert); 142 var kiPropIss = X509.getPublicKeyInfoPropOfCertPEM(issuerCert); 143 var issuerKeyHex = kiPropIss.keyhex; 144 145 var serialNumberHex = xSbj.getSerialNumberHex(); 146 var issuerNameHashHex = KJUR.crypto.Util.hashHex(xIss.getSubjectHex(), algName); 147 var issuerKeyHashHex = KJUR.crypto.Util.hashHex(issuerKeyHex, algName); 148 this.setByValue(issuerNameHashHex, issuerKeyHashHex, 149 serialNumberHex, algName); 150 this.hoge = xSbj.getSerialNumberHex(); 151 }; 152 153 this.getEncodedHex = function() { 154 if (this.dHashAlg === null && 155 this.dIssuerNameHash === null && 156 this.dIssuerKeyHash === null && 157 this.dSerialNumber === null) 158 throw "not yet set values"; 159 160 var a = [this.dHashAlg, this.dIssuerNameHash, 161 this.dIssuerKeyHash, this.dSerialNumber]; 162 var seq = new nA.DERSequence({array: a}); 163 this.hTLV = seq.getEncodedHex(); 164 return this.hTLV; 165 }; 166 167 if (typeof params !== "undefined") { 168 var p = params; 169 if (typeof p.issuerCert !== "undefined" && 170 typeof p.subjectCert !== "undefined") { 171 var alg = KJUR.asn1.ocsp.DEFAULT_HASH; 172 if (typeof p.alg === "undefined") alg = undefined; 173 this.setByCert(p.issuerCert, p.subjectCert, alg); 174 } else if (typeof p.namehash !== "undefined" && 175 typeof p.keyhash !== "undefined" && 176 typeof p.serial !== "undefined") { 177 var alg = KJUR.asn1.ocsp.DEFAULT_HASH; 178 if (typeof p.alg === "undefined") alg = undefined; 179 this.setByValue(p.namehash, p.keyhash, p.serial, alg); 180 } else { 181 throw "invalid constructor arguments"; 182 } 183 } 184 }; 185 YAHOO.lang.extend(KJUR.asn1.ocsp.CertID, KJUR.asn1.ASN1Object); 186 187 /** 188 * ASN.1 Request class for OCSP<br/> 189 * @name KJUR.asn1.ocsp.Request 190 * @class ASN.1 Request class for OCSP 191 * @param {Array} params associative array of parameters 192 * @extends KJUR.asn1.ASN1Object 193 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 194 * @description 195 * Request ASN.1 class is defined in 196 * <a href="https://tools.ietf.org/html/rfc6960#section-4.1.1">RFC 6960 4.1.1</a>. 197 * singleRequestExtensions is not supported yet in this version such as nonce. 198 * <pre> 199 * Request ::= SEQUENCE { 200 * reqCert CertID, 201 * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } 202 * </pre> 203 * @example 204 * // default constructor 205 * o = new KJUR.asn1.ocsp.Request(); 206 * // constructor with certs (sha1 is used by default) 207 * o = new KJUR.asn1.ocsp.Request({issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN..."}); 208 * // constructor with certs and sha256 209 * o = new KJUR.asn1.ocsp.Request({issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg: "sha256"}); 210 * // constructor with values 211 * o = new KJUR.asn1.ocsp.Request({namehash: "1a...", keyhash: "ad...", serial: "1234", alg: "sha256"}); 212 */ 213 KJUR.asn1.ocsp.Request = function(params) { 214 KJUR.asn1.ocsp.Request.superclass.constructor.call(this); 215 this.dReqCert = null; 216 this.dExt = null; 217 218 this.getEncodedHex = function() { 219 var a = []; 220 221 // 1. reqCert 222 if (this.dReqCert === null) 223 throw "reqCert not set"; 224 a.push(this.dReqCert); 225 226 // 2. singleRequestExtensions (not supported yet) 227 228 // 3. construct SEQUENCE 229 var seq = new KJUR.asn1.DERSequence({array: a}); 230 this.hTLV = seq.getEncodedHex(); 231 return this.hTLV; 232 }; 233 234 if (typeof params !== "undefined") { 235 var o = new KJUR.asn1.ocsp.CertID(params); 236 this.dReqCert = o; 237 } 238 }; 239 YAHOO.lang.extend(KJUR.asn1.ocsp.Request, KJUR.asn1.ASN1Object); 240 241 /** 242 * ASN.1 TBSRequest class for OCSP<br/> 243 * @name KJUR.asn1.ocsp.TBSRequest 244 * @class ASN.1 TBSRequest class for OCSP 245 * @param {Array} params associative array of parameters 246 * @extends KJUR.asn1.ASN1Object 247 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 248 * @description 249 * TBSRequest ASN.1 class is defined in 250 * <a href="https://tools.ietf.org/html/rfc6960#section-4.1.1">RFC 6960 4.1.1</a>. 251 * <pre> 252 * TBSRequest ::= SEQUENCE { 253 * version [0] EXPLICIT Version DEFAULT v1, 254 * requestorName [1] EXPLICIT GeneralName OPTIONAL, 255 * requestList SEQUENCE OF Request, 256 * requestExtensions [2] EXPLICIT Extensions OPTIONAL } 257 * </pre> 258 * @example 259 * // default constructor 260 * o = new KJUR.asn1.ocsp.TBSRequest(); 261 * // constructor with requestList parameter 262 * o = new KJUR.asn1.ocsp.TBSRequest({reqList:[ 263 * {issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg:}, 264 * {issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg: "sha256"} 265 * ]}); 266 */ 267 KJUR.asn1.ocsp.TBSRequest = function(params) { 268 KJUR.asn1.ocsp.TBSRequest.superclass.constructor.call(this); 269 this.version = 0; 270 this.dRequestorName = null; 271 this.dRequestList = []; 272 this.dRequestExt = null; 273 274 /** 275 * set TBSRequest ASN.1 object by array of parameters.<br/> 276 * @name setRequestListByParam 277 * @memberOf KJUR.asn1.ocsp.TBSRequest# 278 * @function 279 * @param {Array} aParams array of parameters for Request class 280 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 281 * @example 282 * o = new KJUR.asn1.ocsp.TBSRequest(); 283 * o.setRequestListByParam([ 284 * {issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg:}, 285 * {issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg: "sha256"} 286 * ]); 287 */ 288 this.setRequestListByParam = function(aParams) { 289 var a = []; 290 for (var i = 0; i < aParams.length; i++) { 291 var dReq = new KJUR.asn1.ocsp.Request(aParams[0]); 292 a.push(dReq); 293 } 294 this.dRequestList = a; 295 }; 296 297 this.getEncodedHex = function() { 298 var a = []; 299 300 // 1. version 301 if (this.version !== 0) 302 throw "not supported version: " + this.version; 303 304 // 2. requestorName 305 if (this.dRequestorName !== null) 306 throw "requestorName not supported"; 307 308 // 3. requestList 309 var seqRequestList = 310 new KJUR.asn1.DERSequence({array: this.dRequestList}); 311 a.push(seqRequestList); 312 313 // 4. requestExtensions 314 if (this.dRequestExt !== null) 315 throw "requestExtensions not supported"; 316 317 // 5. construct SEQUENCE 318 var seq = new KJUR.asn1.DERSequence({array: a}); 319 this.hTLV = seq.getEncodedHex(); 320 return this.hTLV; 321 }; 322 323 if (typeof params !== "undefined") { 324 if (typeof params.reqList !== "undefined") 325 this.setRequestListByParam(params.reqList); 326 } 327 }; 328 YAHOO.lang.extend(KJUR.asn1.ocsp.TBSRequest, KJUR.asn1.ASN1Object); 329 330 331 /** 332 * ASN.1 OCSPRequest class for OCSP<br/> 333 * @name KJUR.asn1.ocsp.OCSPRequest 334 * @class ASN.1 OCSPRequest class for OCSP 335 * @param {Array} params associative array of parameters 336 * @extends KJUR.asn1.ASN1Object 337 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 338 * @description 339 * OCSPRequest ASN.1 class is defined in 340 * <a href="https://tools.ietf.org/html/rfc6960#section-4.1.1">RFC 6960 4.1.1</a>. 341 * A signed request is not supported yet in this version. 342 * <pre> 343 * OCSPRequest ::= SEQUENCE { 344 * tbsRequest TBSRequest, 345 * optionalSignature [0] EXPLICIT Signature OPTIONAL } 346 * </pre> 347 * @example 348 * // default constructor 349 * o = new KJUR.asn1.ocsp.OCSPRequest(); 350 * // constructor with requestList parameter 351 * o = new KJUR.asn1.ocsp.OCSPRequest({reqList:[ 352 * {issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg:}, 353 * {issuerCert: "-----BEGIN...", subjectCert: "-----BEGIN...", alg: "sha256"} 354 * ]}); 355 */ 356 KJUR.asn1.ocsp.OCSPRequest = function(params) { 357 KJUR.asn1.ocsp.OCSPRequest.superclass.constructor.call(this); 358 this.dTbsRequest = null; 359 this.dOptionalSignature = null; 360 361 this.getEncodedHex = function() { 362 var a = []; 363 364 // 1. tbsRequest 365 if (this.dTbsRequest !== null) { 366 a.push(this.dTbsRequest); 367 } else { 368 throw "tbsRequest not set"; 369 } 370 371 // 2. optionalSignature 372 if (this.dOptionalSignature !== null) 373 throw "optionalSignature not supported"; 374 375 // 3. construct SEQUENCE 376 var seq = new KJUR.asn1.DERSequence({array: a}); 377 this.hTLV = seq.getEncodedHex(); 378 return this.hTLV; 379 }; 380 381 if (typeof params !== "undefined") { 382 if (typeof params.reqList !== "undefined") { 383 var o = new KJUR.asn1.ocsp.TBSRequest(params); 384 this.dTbsRequest = o; 385 } 386 } 387 }; 388 YAHOO.lang.extend(KJUR.asn1.ocsp.OCSPRequest, KJUR.asn1.ASN1Object); 389 390 /** 391 * Utility class for OCSP<br/> 392 * @name KJUR.asn1.ocsp.OCSPUtil 393 * @class Utility class for OCSP 394 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 395 * @description 396 * This class provides utility static methods for OCSP. 397 * <ul> 398 * <li>{@link KJUR.asn1.ocsp.OCSPUtil.getRequestHex} - generates hexadecimal string of OCSP request</li> 399 * </ul> 400 */ 401 KJUR.asn1.ocsp.OCSPUtil = {}; 402 403 /** 404 * generates hexadecimal string of OCSP request<br/> 405 * @name getRequestHex 406 * @memberOf KJUR.asn1.ocsp.OCSPUtil 407 * @function 408 * @param {String} issuerCert string of PEM issuer certificate 409 * @param {String} subjectCert string of PEM subject certificate to be verified by OCSP 410 * @param {String} algName hash algorithm name used for above arguments (ex. "sha1") DEFAULT: sha1 411 * @return {String} hexadecimal string of generated OCSP request 412 * @since jsrsasign 6.1.0 asn1ocsp 1.0.0 413 * @description 414 * This static method generates hexadecimal string of OCSP request. 415 * @example 416 * // generate OCSP request using sha1 algorithnm by default. 417 * hReq = KJUR.asn1.ocsp.OCSPUtil.getRequestHex("-----BEGIN...", "-----BEGIN..."); 418 */ 419 KJUR.asn1.ocsp.OCSPUtil.getRequestHex = function(issuerCert, subjectCert, alg) { 420 if (alg === undefined) alg = KJUR.asn1.ocsp.DEFAULT_HASH; 421 var param = {alg: alg, issuerCert: issuerCert, subjectCert: subjectCert}; 422 var o = new KJUR.asn1.ocsp.OCSPRequest({reqList: [param]}); 423 return o.getEncodedHex(); 424 }; 425 426 /** 427 * parse OCSPResponse<br/> 428 * @name getOCSPResponseInfo 429 * @memberOf KJUR.asn1.ocsp.OCSPUtil 430 * @function 431 * @param {String} h hexadecimal string of DER OCSPResponse 432 * @return {Object} JSON object of parsed OCSPResponse 433 * @since jsrsasign 6.1.0 asn1ocsp 1.0.1 434 * @description 435 * This static method parse a hexadecimal string of DER OCSPResponse and 436 * returns JSON object of its parsed result. 437 * Its result has following properties: 438 * <ul> 439 * <li>responseStatus - integer of responseStatus</li> 440 * <li>certStatus - string of certStatus (ex. good, revoked or unknown)</li> 441 * <li>thisUpdate - string of thisUpdate in Zulu(ex. 20151231235959Z)</li> 442 * <li>nextUpdate - string of nextUpdate in Zulu(ex. 20151231235959Z)</li> 443 * </ul> 444 * @example 445 * info = KJUR.asn1.ocsp.OCSPUtil.getOCSPResponseInfo("3082..."); 446 */ 447 KJUR.asn1.ocsp.OCSPUtil.getOCSPResponseInfo = function(h) { 448 var result = {}; 449 try { 450 var v = ASN1HEX.getVbyList(h, 0, [0], "0a"); 451 result.responseStatus = parseInt(v, 16); 452 } catch(ex) {}; 453 if (result.responseStatus !== 0) return result; 454 455 try { 456 // certStatus 457 var idxCertStatus = ASN1HEX.getDecendantIndexByNthList(h, 0, [1,0,1,0,0,2,0,1]); 458 if (h.substr(idxCertStatus, 2) === "80") { 459 result.certStatus = "good"; 460 } else if (h.substr(idxCertStatus, 2) === "a1") { 461 result.certStatus = "revoked"; 462 result.revocationTime = 463 hextoutf8(ASN1HEX.getDecendantHexVByNthList(h, idxCertStatus, [0])); 464 } else if (h.substr(idxCertStatus, 2) === "82") { 465 result.certStatus = "unknown"; 466 } 467 } catch (ex) {}; 468 469 // thisUpdate 470 try { 471 var idxThisUpdate = ASN1HEX.getDecendantIndexByNthList(h, 0, [1,0,1,0,0,2,0,2]); 472 result.thisUpdate = hextoutf8(ASN1HEX.getHexOfV_AtObj(h, idxThisUpdate)); 473 } catch (ex) {}; 474 475 // nextUpdate 476 try { 477 var idxEncapNextUpdate = ASN1HEX.getDecendantIndexByNthList(h, 0, [1,0,1,0,0,2,0,3]); 478 if (h.substr(idxEncapNextUpdate, 2) === "a0") { 479 result.nextUpdate = 480 hextoutf8(ASN1HEX.getDecendantHexVByNthList(h, idxEncapNextUpdate, [0])); 481 } 482 } catch (ex) {}; 483 484 return result; 485 }; 486 487