Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  test_qwacs.js

  Sprache: JAVA
 

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

"use strict";

do_get_profile(); // must be called before getting nsIX509CertDB
const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
  Ci.nsIX509CertDB
);

const { QWACs } = ChromeUtils.importESModule(
  "resource://gre/modules/psm/QWACs.sys.mjs"
);

async function verify_1_qwacs(filename, expectSuccess, extraCertNames = []) {
  let cert = constructCertFromFile(filename);
  let result = await certdb.asyncVerifyQWAC(
    Ci.nsIX509CertDB.OneQWAC,
    cert,
    "example.com",
    extraCertNames.map(filename => constructCertFromFile(filename))
  );
  equal(
    result,
    expectSuccess,
    `${filename} ${expectSuccess ? "should" : "should not"} verify as 1-QWAC`
  );
}

add_task(async function test_verify_1_qwacs() {
  Services.prefs.clearUserPref("security.qwacs.enable_test_trust_anchors");
  // By default, the QWACs test trust anchors are not used.
  await verify_1_qwacs("test_qwacs/1-qwac.pem"false);
  await verify_1_qwacs("test_qwacs/1-qwac-qevcpw.pem"false);

  Services.prefs.setBoolPref("security.qwacs.enable_test_trust_anchors"true);

  await verify_1_qwacs("test_qwacs/1-qwac.pem"true);
  await verify_1_qwacs("test_qwacs/1-qwac-qevcpw.pem"true);

  await verify_1_qwacs("test_qwacs/1-qwac-other-optional-qcs.pem"true);
  await verify_1_qwacs("test_qwacs/1-qwac-unrelated-policy.pem"true);

  // One or more intermediates may be necessary for path building.
  await verify_1_qwacs("test_qwacs/1-qwac-via-intermediate.pem"false);
  await verify_1_qwacs("test_qwacs/1-qwac-via-intermediate.pem"true, [
    "test_qwacs/test-int.pem",
  ]);

  await verify_1_qwacs("test_qwacs/empty-qc-type-statement.pem"false);
  await verify_1_qwacs("test_qwacs/missing-qc-type-statement.pem"false);
  await verify_1_qwacs("test_qwacs/missing-qcs-compliance.pem"false);
  await verify_1_qwacs("test_qwacs/wrong-qc-type.pem"false);
  await verify_1_qwacs("test_qwacs/no-1-qwac-policies.pem"false);
  await verify_1_qwacs("test_qwacs/no-policies.pem"false);
  await verify_1_qwacs("test_qwacs/2-qwac.pem"false);
});

async function verify_2_qwacs(
  filename,
  expectSuccess,
  hostname = "example.com"
) {
  let cert = constructCertFromFile(filename);
  let result = await certdb.asyncVerifyQWAC(
    Ci.nsIX509CertDB.TwoQWAC,
    cert,
    hostname,
    []
  );
  equal(
    result,
    expectSuccess,
    `${filename} ${expectSuccess ? "should" : "should not"} verify as 2-QWAC`
  );
}

add_task(async function test_verify_2_qwacs() {
  Services.prefs.clearUserPref("security.qwacs.enable_test_trust_anchors");
  // By default, the QWACs test trust anchors are not used.
  await verify_2_qwacs("test_qwacs/2-qwac.pem"false);

  Services.prefs.setBoolPref("security.qwacs.enable_test_trust_anchors"true);

  await verify_2_qwacs("test_qwacs/2-qwac.pem"true);

  await verify_2_qwacs("test_qwacs/1-qwac.pem"false);
  await verify_2_qwacs("test_qwacs/2-qwac-no-eku.pem"false);
  await verify_2_qwacs("test_qwacs/2-qwac-tls-server-eku.pem"false);
  await verify_2_qwacs("test_qwacs/2-qwac-multiple-key-purpose-eku.pem"false);
  await verify_2_qwacs("test_qwacs/2-qwac.pem"false"example.org");
});

// Produces base64url(hash(base64url(certificate DER)))
async function certificateHash(certificate, hashAlg) {
  let hash = await crypto.subtle.digest(
    hashAlg.replace("S""SHA-"),
    new Uint8Array(
      stringToArray(
        QWACs.toBase64URLEncoding(arrayToString(certificate.getRawDER()))
      )
    )
  );
  return QWACs.toBase64URLEncoding(arrayToString(new Uint8Array(hash)));
}

const kTLSCertificateBindingEE = constructCertFromFile("test_qwacs/2-qwac.pem");

const kTLSCertificateBindingHeader = {
  alg: "",
  cty: "TLS-Certificate-Binding-v1",
  // RFC 7515 Section 4.1.6: "Each string in the array is a base64-encoded
  // (Section 4 of [RFC4648] -- not base64url-encoded) DER [ITU.X690.2008] PKIX
  // certificate value."
  x5c: [],
  sigD: {
    mId: "http://uri.etsi.org/19182/ObjectIdByURIHash",
    pars: [],
    hashM: "",
    hashV: [],
  },
};

async function makeBindingHeader(
  certificateChain,
  certificatesToBind,
  signingAlg,
  hashAlg
) {
  let header = structuredClone(kTLSCertificateBindingHeader);
  header.alg = signingAlg;
  header.x5c = certificateChain.map(c => btoa(arrayToString(c.getRawDER())));
  header.sigD.hashM = hashAlg;
  for (let toBind of certificatesToBind) {
    header.sigD.pars.push("");
    header.sigD.hashV.push(await certificateHash(toBind, hashAlg));
  }
  return header;
}

add_task(async function test_validate_tls_certificate_binding_header() {
  let serverCertificate = constructCertFromFile("bad_certs/default-ee.pem");
  let testHeader = await makeBindingHeader(
    [kTLSCertificateBindingEE],
    [serverCertificate],
    "RS256",
    "S256"
  );
  let validatedHeader = QWACs.validateTLSCertificateBindingHeader(testHeader);
  ok(validatedHeader, "header should validate successfully");
  deepEqual(validatedHeader.algorithm, {
    name: "RSASSA-PKCS1-v1_5",
    hash: "SHA-256",
  });
  equal(validatedHeader.certificates.length, 1);
  equal(validatedHeader.hashAlg, "SHA-256");
  equal(validatedHeader.hashes.length, 1);

  let headerWithExtraKey = structuredClone(testHeader);
  headerWithExtraKey.extra = "foo";
  ok(
    !QWACs.validateTLSCertificateBindingHeader(headerWithExtraKey),
    "header with extra key should not validate"
  );

  let headerWithExtraSigDKey = structuredClone(testHeader);
  headerWithExtraSigDKey.sigD.additional = "bar";
  ok(
    !QWACs.validateTLSCertificateBindingHeader(headerWithExtraSigDKey),
    "header with extra key in sigD should not parse"
  );

  let headerWithWrongCty = structuredClone(testHeader);
  headerWithWrongCty.cty = "TLS-Certificate-Binding-v2";
  ok(
    !QWACs.validateTLSCertificateBindingHeader(headerWithWrongCty),
    "header with wrong cty should not parse"
  );

  let headerWithWrongMId = structuredClone(testHeader);
  headerWithWrongMId.sigD.mId = "http://example.org";
  ok(
    !QWACs.validateTLSCertificateBindingHeader(headerWithWrongMId),
    "header with wrong sigD.mId should not parse"
  );

  let headerWithTooManyPars = structuredClone(testHeader);
  headerWithTooManyPars.sigD.pars.push("");
  ok(
    !QWACs.validateTLSCertificateBindingHeader(headerWithTooManyPars),
    "header with too many sigD.pars elements should not parse"
  );

  let headerWithInvalidHashV = structuredClone(testHeader);
  headerWithInvalidHashV.sigD.hashV[0] = 1234;
  ok(
    !QWACs.validateTLSCertificateBindingHeader(headerWithInvalidHashV),
    "header with invalid sigD.hashV should not parse"
  );

  let headerWithTooManyHashV = structuredClone(testHeader);
  headerWithTooManyHashV.sigD.hashV.push(headerWithTooManyHashV.sigD.hashV[0]);
  ok(
    !QWACs.validateTLSCertificateBindingHeader(headerWithTooManyHashV),
    "header with too many sigD.hashV elements should not parse"
  );

  let headerWithEmptyX5c = structuredClone(testHeader);
  headerWithEmptyX5c.x5c = [];
  ok(
    !QWACs.validateTLSCertificateBindingHeader(headerWithEmptyX5c),
    "header with empty x5c should not parse"
  );

  let headerWithUnsupportedAlg = structuredClone(testHeader);
  headerWithUnsupportedAlg.alg = "RS384";
  ok(
    !QWACs.validateTLSCertificateBindingHeader(headerWithUnsupportedAlg),
    "header with unsupported alg should not parse"
  );

  let headerWithUnsupportedHashM = structuredClone(testHeader);
  headerWithUnsupportedHashM.sigD.hashM = "S224";
  ok(
    !QWACs.validateTLSCertificateBindingHeader(headerWithUnsupportedHashM),
    "header with unsupported sigD.hashM should not parse"
  );

  let headerWithOptionalHeaders = structuredClone(testHeader);
  headerWithOptionalHeaders.kid = "optional kid";
  headerWithOptionalHeaders.iat = "optional iat";
  ok(
    QWACs.validateTLSCertificateBindingHeader(headerWithOptionalHeaders),
    "header with optional headers should parse"
  );

  let headerWithX5tS256Match = structuredClone(testHeader);
  let signingCertificateHash = await crypto.subtle.digest(
    "SHA-256",
    new Uint8Array(kTLSCertificateBindingEE.getRawDER())
  );
  headerWithX5tS256Match["x5t#S256"] = QWACs.toBase64URLEncoding(
    arrayToString(new Uint8Array(signingCertificateHash))
  );
  ok(
    QWACs.validateTLSCertificateBindingHeader(headerWithX5tS256Match),
    "header with matching x5t#S256 should parse"
  );

  let headerWithX5tS256Mismatch = structuredClone(testHeader);
  headerWithX5tS256Mismatch["x5t#S256"] =
    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
  ok(
    !QWACs.validateTLSCertificateBindingHeader(headerWithX5tS256Mismatch),
    "header with x5t#S256 mismatch should not parse"
  );

  let headerWithBadExp = structuredClone(testHeader);
  headerWithBadExp.exp = "not a number";
  ok(
    !QWACs.validateTLSCertificateBindingHeader(headerWithBadExp),
    "header with bad expiration time should not parse"
  );

  let expiredHeader = structuredClone(testHeader);
  expiredHeader.exp = "946684800";
  ok(
    !QWACs.validateTLSCertificateBindingHeader(expiredHeader),
    "expired header should not parse"
  );

  let unexpiredHeader = structuredClone(testHeader);
  unexpiredHeader.exp = "4102444800";
  ok(
    QWACs.validateTLSCertificateBindingHeader(unexpiredHeader),
    "unexpired header should parse"
  );
});

async function validate_tls_certificate_binding_header_with_algorithms(
  signatureAlg,
  hashAlg,
  expectedSignatureAlg,
  expectedHashAlg
) {
  let serverCertificate = constructCertFromFile("bad_certs/default-ee.pem");
  let testHeader = await makeBindingHeader(
    [kTLSCertificateBindingEE],
    [serverCertificate],
    signatureAlg,
    hashAlg
  );
  let validatedHeader = QWACs.validateTLSCertificateBindingHeader(testHeader);
  ok(validatedHeader, "header should validate successfully");
  deepEqual(validatedHeader.algorithm, expectedSignatureAlg);
  equal(validatedHeader.certificates.length, 1);
  equal(validatedHeader.hashAlg, expectedHashAlg);
  equal(validatedHeader.hashes.length, 1);
}

add_task(
  async function test_validate_tls_certificate_binding_header_with_algorithms() {
    let options = [
      {
        signatureAlg: "RS256",
        hashAlg: "S256",
        expectedSignatureAlg: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
        expectedHashAlg: "SHA-256",
      },
      {
        signatureAlg: "PS256",
        hashAlg: "S384",
        expectedSignatureAlg: {
          name: "RSA-PSS",
          saltLength: 32,
          hash: "SHA-256",
        },
        expectedHashAlg: "SHA-384",
      },
      {
        signatureAlg: "ES256",
        hashAlg: "S512",
        expectedSignatureAlg: {
          name: "ECDSA",
          namedCurve: "P-256",
          hash: "SHA-256",
        },
        expectedHashAlg: "SHA-512",
      },
    ];
    for (let option of options) {
      await validate_tls_certificate_binding_header_with_algorithms(
        option.signatureAlg,
        option.hashAlg,
        option.expectedSignatureAlg,
        option.expectedHashAlg
      );
    }
  }
);

async function sign(privateKeyInfo, algorithm, header) {
  let toSign = new Uint8Array(stringToArray(header + "."));
  let key = await crypto.subtle.importKey(
    "pkcs8",
    privateKeyInfo,
    algorithm,
    true,
    ["sign"]
  );
  let signature = await crypto.subtle.sign(algorithm, key, toSign);
  return (
    header +
    ".." +
    QWACs.toBase64URLEncoding(arrayToString(new Uint8Array(signature)))
  );
}

async function signTLSCertificateBinding(header, key, algorithm) {
  return sign(
    key,
    algorithm,
    QWACs.toBase64URLEncoding(JSON.stringify(header))
  );
}

async function verify_tls_certificate_binding_signature(
  headerSignatureAlgorithm,
  headerHashAlgorithm,
  signatureAlgorithm,
  signingKeyFilename,
  bindingCertificateFilename,
  serverCertificateFilename,
  presentedServerCertificateFilename,
  expectSuccess,
  expectedCertificateSubject
) {
  let signingKey = new Uint8Array(
    stringToArray(
      QWACs.fromBase64URLEncoding(
        pemToBase64(readFile(do_get_file(signingKeyFilename, false)))
      )
    )
  );
  let bindingCertificate = constructCertFromFile(bindingCertificateFilename);
  let serverCertificate = constructCertFromFile(serverCertificateFilename);
  let testHeader = await makeBindingHeader(
    [bindingCertificate],
    [serverCertificate],
    headerSignatureAlgorithm,
    headerHashAlgorithm
  );
  let binding = await signTLSCertificateBinding(
    testHeader,
    signingKey,
    signatureAlgorithm
  );
  let presentedServerCertificate = constructCertFromFile(
    presentedServerCertificateFilename
  );
  let qwac = await QWACs.verifyTLSCertificateBinding(
    binding,
    presentedServerCertificate,
    "example.com"
  );
  equal(
    !!qwac,
    expectSuccess,
    `TLS certificate binding ${expectSuccess ? "should" : "should not"} verify correctly`
  );
  if (expectSuccess) {
    equal(
      qwac.commonName,
      expectedCertificateSubject,
      "Verification should return the expected certificate"
    );
  }
}

add_task(async function test_verify_tls_certificate_binding_signatures() {
  let options = [
    {
      headerSignatureAlgorithm: "RS256",
      headerHashAlgorithm: "S512",
      signatureAlgorithm: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
      signingKeyFilename: "bad_certs/default-ee.key",
      bindingCertificateFilename: "test_qwacs/2-qwac.pem",
      serverCertificateFilename: "bad_certs/default-ee.pem",
      presentedServerCertificateFilename: "bad_certs/default-ee.pem",
      expectSuccess: true,
      expectedCertificateSubject: "2-QWAC",
    },
    // presented server certificate / bound server certificate mismatch
    {
      headerSignatureAlgorithm: "RS256",
      headerHashAlgorithm: "S512",
      signatureAlgorithm: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
      signingKeyFilename: "bad_certs/default-ee.key",
      bindingCertificateFilename: "test_qwacs/2-qwac.pem",
      serverCertificateFilename: "bad_certs/default-ee.pem",
      presentedServerCertificateFilename:
        "bad_certs/ee-from-missing-intermediate.pem",
      expectSuccess: false,
      expectedCertificateSubject: null,
    },
    {
      headerSignatureAlgorithm: "PS256",
      headerHashAlgorithm: "S256",
      signatureAlgorithm: {
        name: "RSA-PSS",
        hash: "SHA-256",
        saltLength: 32,
      },
      signingKeyFilename: "bad_certs/default-ee.key",
      bindingCertificateFilename: "test_qwacs/2-qwac.pem",
      serverCertificateFilename: "bad_certs/default-ee.pem",
      presentedServerCertificateFilename: "bad_certs/default-ee.pem",
      expectSuccess: true,
      expectedCertificateSubject: "2-QWAC",
    },
    {
      headerSignatureAlgorithm: "ES256",
      headerHashAlgorithm: "S384",
      signatureAlgorithm: {
        name: "ECDSA",
        namedCurve: "P-256",
        hash: "SHA-256",
      },
      signingKeyFilename: "test_qwacs/secp256r1.key",
      bindingCertificateFilename: "test_qwacs/2-qwac-ec.pem",
      serverCertificateFilename: "bad_certs/default-ee.pem",
      presentedServerCertificateFilename: "bad_certs/default-ee.pem",
      expectSuccess: true,
      expectedCertificateSubject: "2-QWAC with EC key",
    },
    // header signature algorithm / actual signature algorithm mismatch
    {
      headerSignatureAlgorithm: "RS256",
      headerHashAlgorithm: "S384",
      signatureAlgorithm: {
        name: "ECDSA",
        namedCurve: "P-256",
        hash: "SHA-256",
      },
      signingKeyFilename: "test_qwacs/secp256r1.key",
      bindingCertificateFilename: "test_qwacs/2-qwac-ec.pem",
      serverCertificateFilename: "bad_certs/default-ee.pem",
      presentedServerCertificateFilename: "bad_certs/default-ee.pem",
      expectSuccess: false,
      expectedCertificateSubject: null,
    },
  ];

  for (let option of options) {
    await verify_tls_certificate_binding_signature(
      option.headerSignatureAlgorithm,
      option.headerHashAlgorithm,
      option.signatureAlgorithm,
      option.signingKeyFilename,
      option.bindingCertificateFilename,
      option.serverCertificateFilename,
      option.presentedServerCertificateFilename,
      option.expectSuccess,
      option.expectedCertificateSubject
    );
  }
});

Messung V0.5 in Prozent
C=88 H=100 G=94

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002