test_signed_pdfs.js (14762B)
1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 "use strict"; 6 7 do_get_profile(); // must be called before getting nsIX509CertDB 8 const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( 9 Ci.nsIX509CertDB 10 ); 11 12 // If resolved, asyncVerifyPKCS7Object(pkcs7, data, signatureType) will return an array consisting 13 // of 3 elements for each SignerInfo of the PKCS7 message: 14 // - signatureResult - which describes the result of verifying the hash of data against the signature 15 // stored in pkcs7 16 // - certificateResult - which describes the result of certificate verification 17 // If the signature verification has failed, certificate verification is not run. 18 // - signerCertificate - which returns the signerCertificate from the pkcs7 message 19 // signerCertificate is null if the signature verification has failed (not equal to NS_OK). 20 21 // Empty PKCS7 message should return resolved promise with NS_ERROR_CMS_VERIFY_ERROR_PROCESSING 22 add_task(async function () { 23 info("Running PDF verification service test with empty input"); 24 let pkcs7 = new Uint8Array(); 25 let data = [new Uint8Array(0x10)]; 26 let signatureType = Ci.nsIX509CertDB.ADBE_PKCS7_DETACHED; 27 28 let result = await certdb.asyncVerifyPKCS7Object(pkcs7, data, signatureType); 29 30 equal(result.length, 1); 31 let firstSignatureResult = result[0]; 32 equal( 33 firstSignatureResult.signatureResult, 34 Cr.NS_ERROR_CMS_VERIFY_ERROR_PROCESSING 35 ); 36 equal( 37 firstSignatureResult.certificateResult, 38 Cr.NS_ERROR_CMS_VERIFY_ERROR_PROCESSING 39 ); 40 equal(firstSignatureResult.signerCertificate, null); 41 }); 42 43 // Empty data message should return resolved promise with NS_ERROR_CMS_VERIFY_ERROR_PROCESSING 44 add_task(async function () { 45 info("Running PDF verification service test with empty input"); 46 let pkcs7 = new Uint8Array(0x10); 47 let data = [new Uint8Array()]; 48 let signatureType = Ci.nsIX509CertDB.ADBE_PKCS7_DETACHED; 49 50 let result = await certdb.asyncVerifyPKCS7Object(pkcs7, data, signatureType); 51 52 equal(result.length, 1); 53 let firstSignatureResult = result[0]; 54 equal( 55 firstSignatureResult.signatureResult, 56 Cr.NS_ERROR_CMS_VERIFY_ERROR_PROCESSING 57 ); 58 equal( 59 firstSignatureResult.certificateResult, 60 Cr.NS_ERROR_CMS_VERIFY_ERROR_PROCESSING 61 ); 62 equal(firstSignatureResult.signerCertificate, null); 63 }); 64 65 // ADBE_PKCS7_SHA1 is not supported 66 add_task(async function () { 67 info("Running PDF verification service test with unsupported signature type"); 68 let pkcs7 = new Uint8Array(0x10); 69 let data = [new Uint8Array(0x10)]; 70 let signatureType = Ci.nsIX509CertDB.ADBE_PKCS7_SHA1; 71 72 let result = await certdb.asyncVerifyPKCS7Object(pkcs7, data, signatureType); 73 74 equal(result.length, 1); 75 let firstSignatureResult = result[0]; 76 equal( 77 firstSignatureResult.signatureResult, 78 Cr.NS_ERROR_CMS_VERIFY_ERROR_PROCESSING 79 ); 80 equal( 81 firstSignatureResult.certificateResult, 82 Cr.NS_ERROR_CMS_VERIFY_ERROR_PROCESSING 83 ); 84 equal(firstSignatureResult.signerCertificate, null); 85 }); 86 87 function pkcs7FromFile(certName) { 88 let certFile = do_get_file(`test_pdf_verification/${certName}.p7s`, false); 89 let certBytes = readFile(certFile); 90 let certBytesClean = certBytes 91 .replace("-----BEGIN PKCS7-----", "") 92 .replace("-----END PKCS7-----", "") 93 .replace(/\n/g, ""); 94 const binary = atob(certBytesClean); 95 const len = binary.length; 96 const bytes = new Uint8Array(len); 97 98 for (let i = 0; i < len; i++) { 99 bytes[i] = binary.charCodeAt(i); 100 } 101 102 return bytes; 103 } 104 105 function readBinFromFile(dataName) { 106 let dataFile = do_get_file(`test_pdf_verification/${dataName}.bin`, false); 107 108 let fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance( 109 Ci.nsIFileInputStream 110 ); 111 fstream.init(dataFile, -1, 0, 0); 112 let available = fstream.available(); 113 let data = available > 0 ? NetUtil.readInputStream(fstream, available) : ""; 114 fstream.close(); 115 116 return new Uint8Array(data); 117 } 118 119 // PKCS7 CMS message with the correct signature should return resolve promise 120 // with signatureResult to be equal to NS_OK 121 // and the signerCertificate being not null. 122 // Currently, certificate verification is not supported. 123 add_task(async function () { 124 info("Running PDF verification service test with a correct signature"); 125 let pkcs7 = pkcs7FromFile("cert_correct"); 126 let data = [readBinFromFile("data_correct")]; 127 let signatureType = Ci.nsIX509CertDB.ADBE_PKCS7_DETACHED; 128 129 let result = await certdb.asyncVerifyPKCS7Object(pkcs7, data, signatureType); 130 let firstSignatureResult = result[0]; 131 132 equal(result.length, 1); 133 equal(firstSignatureResult.signatureResult, Cr.NS_OK); 134 equal( 135 firstSignatureResult.certificateResult, 136 Cr.NS_ERROR_CMS_VERIFY_NOT_YET_ATTEMPTED 137 ); 138 ok( 139 firstSignatureResult.signerCertificate, 140 "Signer certificate should not be null/undefined" 141 ); 142 }); 143 144 // PKCS7 CMS message with the correct signature should return resolve promise 145 // with signatureResult to be equal to NS_OK 146 // and the signerCertificate being not null. 147 // Currently, certificate verification is not supported. 148 add_task(async function () { 149 info("Running PDF verification service test with a correct signature"); 150 let pkcs7 = pkcs7FromFile("certificate_two_data_inputs"); 151 // each dataPortion here is an Uint8Array 152 let dataPortion = readBinFromFile("data_correct"); 153 let data = [dataPortion, dataPortion]; 154 let signatureType = Ci.nsIX509CertDB.ADBE_PKCS7_DETACHED; 155 156 let result = await certdb.asyncVerifyPKCS7Object(pkcs7, data, signatureType); 157 158 equal(result.length, 1); 159 let firstSignatureResult = result[0]; 160 equal(firstSignatureResult.signatureResult, Cr.NS_OK); 161 equal( 162 firstSignatureResult.certificateResult, 163 Cr.NS_ERROR_CMS_VERIFY_NOT_YET_ATTEMPTED 164 ); 165 ok( 166 firstSignatureResult.signerCertificate, 167 "Signer certificate should not be null/undefined" 168 ); 169 }); 170 171 // PKCS7 CMS message contains one SignerInfo with an incorrect signature. 172 add_task(async function () { 173 info("Running PDF verification service test with a incorrect signature"); 174 let pkcs7 = pkcs7FromFile("cert_with_incorrect_signature"); 175 let data = [readBinFromFile("data_correct")]; 176 let signatureType = Ci.nsIX509CertDB.ADBE_PKCS7_DETACHED; 177 178 let result = await certdb.asyncVerifyPKCS7Object(pkcs7, data, signatureType); 179 equal(result.length, 1); 180 let firstSignatureResult = result[0]; 181 182 equal( 183 firstSignatureResult.signatureResult, 184 getXPCOMStatusFromNSS(SEC_ERROR_PKCS7_BAD_SIGNATURE) 185 ); 186 equal( 187 firstSignatureResult.certificateResult, 188 Cr.NS_ERROR_CMS_VERIFY_NOT_YET_ATTEMPTED 189 ); 190 equal(firstSignatureResult.signerCertificate, null); 191 }); 192 193 // MD5 signatures are not supported. 194 add_task(async function () { 195 info("Running PDF verification service test with a md5 signature"); 196 let pkcs7 = pkcs7FromFile("md5_signer_info"); 197 let data = [readBinFromFile("data_correct")]; 198 let signatureType = Ci.nsIX509CertDB.ADBE_PKCS7_DETACHED; 199 200 let result = await certdb.asyncVerifyPKCS7Object(pkcs7, data, signatureType); 201 equal(result.length, 1); 202 let firstSignatureResult = result[0]; 203 204 equal( 205 firstSignatureResult.signatureResult, 206 Cr.NS_ERROR_CMS_VERIFY_NOT_SIGNED 207 ); 208 equal( 209 firstSignatureResult.certificateResult, 210 Cr.NS_ERROR_CMS_VERIFY_NOT_YET_ATTEMPTED 211 ); 212 equal(firstSignatureResult.signerCertificate, null); 213 }); 214 215 // PKCS7 CMS message has 2 SignerInfo, both have correct signature (sha1/sha2) 216 add_task(async function () { 217 info( 218 "Running PDF verification service test with the CMS message containing two different SignerInfo, both have correct signatures" 219 ); 220 let pkcs7 = pkcs7FromFile("two_correct_signatures"); 221 let data = [readBinFromFile("data_correct")]; 222 let signatureType = Ci.nsIX509CertDB.ADBE_PKCS7_DETACHED; 223 224 let result = await certdb.asyncVerifyPKCS7Object(pkcs7, data, signatureType); 225 // 2 SignerInfo results into 2 signature results 226 equal(result.length, 2); 227 let firstSignatureResult = result[0]; 228 let secondSignatureResult = result[1]; 229 230 equal(firstSignatureResult.signatureResult, Cr.NS_OK); 231 equal( 232 firstSignatureResult.certificateResult, 233 Cr.NS_ERROR_CMS_VERIFY_NOT_YET_ATTEMPTED 234 ); 235 ok( 236 firstSignatureResult.signerCertificate, 237 "Signer certificate should not be null/undefined" 238 ); 239 240 equal(secondSignatureResult.signatureResult, Cr.NS_OK); 241 equal( 242 secondSignatureResult.certificateResult, 243 Cr.NS_ERROR_CMS_VERIFY_NOT_YET_ATTEMPTED 244 ); 245 ok( 246 secondSignatureResult.signerCertificate, 247 "Signer certificate should not be null/undefined" 248 ); 249 }); 250 251 // PKCS7 CMS message has 2 SignerInfo, one SignerInfo has a wrong digest 252 // We consider that the signature is verified iff all the SignerInfo contain the correct signature. 253 add_task(async function () { 254 info( 255 "Running PDF verification service test with the CMS message containing two different SignerInfo, only one has a correct signature" 256 ); 257 let pkcs7 = pkcs7FromFile("one_correct_one_incorrect_hash"); 258 let data = [readBinFromFile("data_correct")]; 259 let signatureType = Ci.nsIX509CertDB.ADBE_PKCS7_DETACHED; 260 261 let result = await certdb.asyncVerifyPKCS7Object(pkcs7, data, signatureType); 262 equal(result.length, 2); 263 let firstSignatureResult = result[0]; 264 let secondSignatureResult = result[1]; 265 266 equal(firstSignatureResult.signatureResult, Cr.NS_OK); 267 equal( 268 firstSignatureResult.certificateResult, 269 Cr.NS_ERROR_CMS_VERIFY_NOT_YET_ATTEMPTED 270 ); 271 ok( 272 firstSignatureResult.signerCertificate, 273 "Signer certificate should not be null/undefined" 274 ); 275 276 equal( 277 secondSignatureResult.signatureResult, 278 getXPCOMStatusFromNSS(SEC_ERROR_PKCS7_BAD_SIGNATURE) 279 ); 280 equal( 281 secondSignatureResult.certificateResult, 282 Cr.NS_ERROR_CMS_VERIFY_NOT_YET_ATTEMPTED 283 ); 284 equal(secondSignatureResult.signerCertificate, null); 285 }); 286 287 // PKCS7 CMS message has 2 SignerInfo, one SignerInfo has a correct digest, but an incorrect signature 288 add_task(async function () { 289 info( 290 "Running PDF verification service test with the CMS message containing two different SignerInfo, only one has a correct signature" 291 ); 292 let pkcs7 = pkcs7FromFile("one_correct_one_incorrect_signature"); 293 let data = [readBinFromFile("data_correct")]; 294 let signatureType = Ci.nsIX509CertDB.ADBE_PKCS7_DETACHED; 295 296 let result = await certdb.asyncVerifyPKCS7Object(pkcs7, data, signatureType); 297 let firstSignatureResult = result[0]; 298 let secondSignatureResult = result[1]; 299 300 equal(firstSignatureResult.signatureResult, Cr.NS_OK); 301 equal( 302 firstSignatureResult.certificateResult, 303 Cr.NS_ERROR_CMS_VERIFY_NOT_YET_ATTEMPTED 304 ); 305 ok( 306 firstSignatureResult.signerCertificate, 307 "Signer certificate should not be null/undefined" 308 ); 309 310 equal( 311 secondSignatureResult.signatureResult, 312 getXPCOMStatusFromNSS(SEC_ERROR_PKCS7_BAD_SIGNATURE) 313 ); 314 equal( 315 secondSignatureResult.certificateResult, 316 Cr.NS_ERROR_CMS_VERIFY_NOT_YET_ATTEMPTED 317 ); 318 equal(secondSignatureResult.signerCertificate, null); 319 }); 320 321 // PKCS7 CMS message with no SignerInfo 322 add_task(async function () { 323 info("Running PDF verification service test with no SignerInfo"); 324 let pkcs7 = pkcs7FromFile("no_signer_info"); 325 let data = [readBinFromFile("data_correct")]; 326 let signatureType = Ci.nsIX509CertDB.ADBE_PKCS7_DETACHED; 327 328 let result = await certdb.asyncVerifyPKCS7Object(pkcs7, data, signatureType); 329 equal(result.length, 1); 330 let firstSignatureResult = result[0]; 331 332 equal( 333 firstSignatureResult.signatureResult, 334 Cr.NS_ERROR_CMS_VERIFY_ERROR_PROCESSING 335 ); 336 equal( 337 firstSignatureResult.certificateResult, 338 Cr.NS_ERROR_CMS_VERIFY_ERROR_PROCESSING 339 ); 340 equal(firstSignatureResult.signerCertificate, null); 341 }); 342 343 // PKCS7 CMS message with no certificates 344 add_task(async function () { 345 info("Running PDF verification service test with an empty certificate list"); 346 let pkcs7 = pkcs7FromFile("no_certificate"); 347 let data = [readBinFromFile("data_correct")]; 348 let signatureType = Ci.nsIX509CertDB.ADBE_PKCS7_DETACHED; 349 350 let result = await certdb.asyncVerifyPKCS7Object(pkcs7, data, signatureType); 351 equal(result.length, 1); 352 let firstSignatureResult = result[0]; 353 354 equal(firstSignatureResult.signatureResult, Cr.NS_ERROR_CMS_VERIFY_NOCERT); 355 equal( 356 firstSignatureResult.certificateResult, 357 Cr.NS_ERROR_CMS_VERIFY_NOT_YET_ATTEMPTED 358 ); 359 equal(firstSignatureResult.signerCertificate, null); 360 }); 361 362 // Test vector used in Poppler to test their implementation 363 // SignerCertificate subject name is "CN=RSA2048 test key for pdfsig" 364 add_task(async function () { 365 info("Running PDF verification service test with the Poppler TV"); 366 let pkcs7 = pkcs7FromFile("poppler_signature"); 367 let data = [readBinFromFile("poppler_data")]; 368 let signatureType = Ci.nsIX509CertDB.ADBE_PKCS7_DETACHED; 369 370 let result = await certdb.asyncVerifyPKCS7Object(pkcs7, data, signatureType); 371 equal(result.length, 1); 372 let firstSignatureResult = result[0]; 373 374 equal(firstSignatureResult.signatureResult, Cr.NS_OK); 375 equal( 376 firstSignatureResult.certificateResult, 377 Cr.NS_ERROR_CMS_VERIFY_NOT_YET_ATTEMPTED 378 ); 379 380 ok( 381 firstSignatureResult.signerCertificate, 382 "Signer certificate should not be null/undefined" 383 ); 384 info( 385 "Certificate Subject Name: " + 386 firstSignatureResult.signerCertificate.subjectName 387 ); 388 Assert.equal( 389 firstSignatureResult.signerCertificate.subjectName, 390 "CN=RSA2048 test key for pdfsig" 391 ); 392 }); 393 394 // Checking some of the properties of the returned certificate 395 // The certificate was generated to have the Issuer "Test" and the subjectName "Test" 396 add_task(async function () { 397 info("Running PDF verification service test with a correct signature"); 398 let pkcs7 = pkcs7FromFile("cert_correct"); 399 let data = [readBinFromFile("data_correct")]; 400 let signatureType = Ci.nsIX509CertDB.ADBE_PKCS7_DETACHED; 401 402 let result = await certdb.asyncVerifyPKCS7Object(pkcs7, data, signatureType); 403 equal(result.length, 1); 404 let firstSignatureResult = result[0]; 405 406 equal(firstSignatureResult.signatureResult, Cr.NS_OK); 407 equal( 408 firstSignatureResult.certificateResult, 409 Cr.NS_ERROR_CMS_VERIFY_NOT_YET_ATTEMPTED 410 ); 411 412 ok( 413 firstSignatureResult.signerCertificate, 414 "Signer certificate should not be null/undefined" 415 ); 416 417 info( 418 "Certificate Subject Name: " + 419 firstSignatureResult.signerCertificate.subjectName 420 ); 421 Assert.equal(firstSignatureResult.signerCertificate.subjectName, "CN=Test"); 422 423 info( 424 "Certificate Issuer Name: " + 425 firstSignatureResult.signerCertificate.issuerName 426 ); 427 Assert.equal(firstSignatureResult.signerCertificate.issuerName, "CN=Test"); 428 });