tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 });