diff --git a/security/nss/.taskcluster.yml b/security/nss/.taskcluster.yml index 494d31a7b0..4fffc9c82b 100644 --- a/security/nss/.taskcluster.yml +++ b/security/nss/.taskcluster.yml @@ -1,47 +1,37 @@ +# This file is rendered via JSON-e in a hook with context: +# { +# tasks_for: 'hg-push', +# push: {owner, pushlog_id, pushdate}, +# repository: {url, project, level}, +# now, +# ownTaskId: // taskId of the task that will be created +# } --- -version: 0 -metadata: - name: "NSS Continuous Integration" - description: "The Taskcluster task graph for the NSS tree" - owner: "mozilla-taskcluster-maintenance@mozilla.com" - source: {{{source}}} - -scopes: - # Note the below scopes are insecure however these get overriden on the server - # side to whatever scopes are set by mozilla-taskcluster. - - queue:* - - docker-worker:* - - scheduler:* - -# Available mustache parameters (see the mozilla-taskcluster source): -# -# - owner: push user (email address) -# - source: URL of this YAML file -# - url: repository URL -# - project: alias for the destination repository (basename of -# the repo url) -# - level: SCM level of the destination repository -# (1 = try, 3 = core) -# - revision: (short) hg revision of the head of the push -# - revision_hash: (long) hg revision of the head of the push -# - comment: comment of the push -# - pushlog_id: id in the pushlog table of the repository -# -# and functions: -# - as_slugid: convert a label into a slugId -# - from_now: generate a timestamp at a fixed offset from now - +version: 1 tasks: - - taskId: '{{#as_slugid}}decision task{{/as_slugid}}' - reruns: 3 - task: - created: '{{now}}' - deadline: '{{#from_now}}1 day{{/from_now}}' - expires: '{{#from_now}}14 days{{/from_now}}' + - $let: + # sometimes the push user is just `ffxbld` or the like, but we want an + # email-like field.. + ownerEmail: + $if: '"@" in push.owner' + then: '${push.owner}' + else: '${push.owner}@noreply.mozilla.org' + # ensure there's no trailing `/` on the repo URL + repoUrl: + $if: 'repository.url[-1] == "/"' + then: {$eval: 'repository.url[:-1]'} + else: {$eval: 'repository.url'} + in: + taskId: '${ownTaskId}' + taskGroupId: '${ownTaskId}' + schedulerId: 'nss-level-${repository.level}' + created: {$fromNow: ''} + deadline: {$fromNow: '1 day'} + expires: {$fromNow: '14 days'} metadata: owner: mozilla-taskcluster-maintenance@mozilla.com - source: {{{source}}} + source: "${repository.url}" name: "NSS Decision Task" description: | The task that creates all of the other tasks in the task graph @@ -49,24 +39,26 @@ tasks: workerType: "hg-worker" provisionerId: "aws-provisioner-v1" + scopes: + - 'assume:repo:${repoUrl[8:]}:branch:default' tags: - createdForUser: {{owner}} + createdForUser: "${ownerEmail}" routes: - - "tc-treeherder-stage.v2.{{project}}.{{revision}}.{{pushlog_id}}" - - "tc-treeherder.v2.{{project}}.{{revision}}.{{pushlog_id}}" + - "tc-treeherder-stage.v2.${repository.project}.${push.revision}.${push.pushlog_id}" + - "tc-treeherder.v2.${repository.project}.${push.revision}.${push.pushlog_id}" payload: - image: nssdev/nss-decision:0.0.2 + # TODO: use nssdev org , not djmitche, once the image is pushed there + image: djmitche/nss-decision:0.0.3 env: - TC_OWNER: {{owner}} - TC_SOURCE: {{{source}}} - TC_PROJECT: {{project}} - TC_COMMENT: '{{comment}}' - NSS_PUSHLOG_ID: '{{pushlog_id}}' - NSS_HEAD_REPOSITORY: '{{{url}}}' - NSS_HEAD_REVISION: '{{revision}}' + TC_OWNER: "${push.owner}" + TC_SOURCE: "${repository.url}" + TC_PROJECT: ${repository.project} + NSS_PUSHLOG_ID: '${push.pushlog_id}' + NSS_HEAD_REPOSITORY: '${repository.url}' + NSS_HEAD_REVISION: '${push.revision}' maxRunTime: 1800 diff --git a/security/nss/automation/abi-check/expected-report-libnss3.so.txt b/security/nss/automation/abi-check/expected-report-libnss3.so.txt index a4c7673101..c24dae4253 100644 --- a/security/nss/automation/abi-check/expected-report-libnss3.so.txt +++ b/security/nss/automation/abi-check/expected-report-libnss3.so.txt @@ -1,5 +1,5 @@ 1 Added function: - 'function SECOidTag HASH_GetHashOidTagByHashType(HASH_HashType)' {HASH_GetHashOidTagByHashType@@NSS_3.43} + 'function SECStatus CERT_GetCertificateDer(const CERTCertificate*, SECItem*)' {CERT_GetCertificateDer@@NSS_3.44} diff --git a/security/nss/automation/abi-check/previous-nss-release b/security/nss/automation/abi-check/previous-nss-release index d7418dbfda..da7472286f 100644 --- a/security/nss/automation/abi-check/previous-nss-release +++ b/security/nss/automation/abi-check/previous-nss-release @@ -1 +1 @@ -NSS_3_42_BRANCH +NSS_3_43_BRANCH diff --git a/security/nss/automation/taskcluster/docker-decision/Dockerfile b/security/nss/automation/taskcluster/docker-decision/Dockerfile index e0a31641e5..8ce08a8f2b 100644 --- a/security/nss/automation/taskcluster/docker-decision/Dockerfile +++ b/security/nss/automation/taskcluster/docker-decision/Dockerfile @@ -9,6 +9,7 @@ RUN apt-get update \ locales \ mercurial \ nodejs \ + npm \ && rm -rf /var/lib/apt/lists/* \ && apt-get autoremove -y && apt-get clean -y diff --git a/security/nss/automation/taskcluster/graph/npm-shrinkwrap.json b/security/nss/automation/taskcluster/graph/npm-shrinkwrap.json index b805bb8ed2..b5d4ddc53e 100644 --- a/security/nss/automation/taskcluster/graph/npm-shrinkwrap.json +++ b/security/nss/automation/taskcluster/graph/npm-shrinkwrap.json @@ -1,1643 +1,3053 @@ { "name": "decision-task", "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, "dependencies": { "amqplib": { "version": "0.4.2", - "from": "amqplib@>=0.4.1 <0.5.0", "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.4.2.tgz", + "integrity": "sha1-XkoqkUzLMSX5y5H22gfJeqTLE6Y=", + "requires": { + "bitsyntax": "~0.0.4", + "buffer-more-ints": "0.0.2", + "readable-stream": "1.x >=1.1.9", + "when": "~3.6.2" + }, "dependencies": { "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, "readable-stream": { "version": "1.1.14", - "from": "readable-stream@>=1.0.0 <2.0.0 >=1.1.9", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } } } }, "ansi-regex": { "version": "2.0.0", - "from": "ansi-regex@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", + "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=" }, "ansi-styles": { "version": "2.2.1", - "from": "ansi-styles@>=2.1.0 <3.0.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "anymatch": { "version": "1.3.0", - "from": "anymatch@>=1.3.0 <2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz" + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz", + "integrity": "sha1-o+Uvo5FoyCX/V7AkgSbOWo/5VQc=", + "optional": true, + "requires": { + "arrify": "^1.0.0", + "micromatch": "^2.1.5" + } }, "argparse": { "version": "1.0.9", - "from": "argparse@>=1.0.7 <2.0.0", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz" + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "requires": { + "sprintf-js": "~1.0.2" + } }, "arr-diff": { "version": "2.0.0", - "from": "arr-diff@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "optional": true, + "requires": { + "arr-flatten": "^1.0.1" + } }, "arr-flatten": { "version": "1.0.1", - "from": "arr-flatten@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.1.tgz", + "integrity": "sha1-5f/lTUXhnzLyFukeuZyM6JK7YEs=", + "optional": true }, "array-find-index": { "version": "1.0.2", - "from": "array-find-index@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" }, "array-uniq": { "version": "1.0.3", - "from": "array-uniq@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" }, "array-unique": { "version": "0.2.1", - "from": "array-unique@>=0.2.1 <0.3.0", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz" + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "optional": true }, "arrify": { "version": "1.0.1", - "from": "arrify@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "optional": true }, "asap": { "version": "1.0.0", - "from": "asap@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz", + "integrity": "sha1-sqRdpf36ILBJb8N2jMJ8EvqRan0=" }, "asn1": { "version": "0.2.3", - "from": "asn1@>=0.2.3 <0.3.0", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz" + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" }, "assert-plus": { "version": "0.2.0", - "from": "assert-plus@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" }, "async": { "version": "2.1.1", - "from": "async@*", - "resolved": "https://registry.npmjs.org/async/-/async-2.1.1.tgz" + "resolved": "https://registry.npmjs.org/async/-/async-2.1.1.tgz", + "integrity": "sha1-4RttEAQ/IlTvthohFj2EDM3bjSg=", + "requires": { + "lodash": "^4.14.0" + } }, "async-each": { "version": "1.0.1", - "from": "async-each@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "optional": true }, "asynckit": { "version": "0.4.0", - "from": "asynckit@>=0.4.0 <0.5.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "aws-sign2": { "version": "0.6.0", - "from": "aws-sign2@>=0.6.0 <0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz" + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" }, "aws4": { "version": "1.5.0", - "from": "aws4@>=1.2.1 <2.0.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.5.0.tgz" + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.5.0.tgz", + "integrity": "sha1-Cin/t5wxyecS7rCH6OemS0pW11U=" }, "babel-cli": { "version": "6.16.0", - "from": "babel-cli@>=6.14.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.16.0.tgz" + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.16.0.tgz", + "integrity": "sha1-Tg0c9ARC73gzD3/viOs6ChsWvTc=", + "requires": { + "babel-core": "^6.16.0", + "babel-polyfill": "^6.16.0", + "babel-register": "^6.16.0", + "babel-runtime": "^6.9.0", + "bin-version-check": "^2.1.0", + "chalk": "1.1.1", + "chokidar": "^1.0.0", + "commander": "^2.8.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^0.1.0", + "glob": "^5.0.5", + "lodash": "^4.2.0", + "log-symbols": "^1.0.2", + "output-file-sync": "^1.1.0", + "path-exists": "^1.0.0", + "path-is-absolute": "^1.0.0", + "request": "^2.65.0", + "slash": "^1.0.0", + "source-map": "^0.5.0", + "v8flags": "^2.0.10" + } }, "babel-code-frame": { "version": "6.16.0", - "from": "babel-code-frame@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.16.0.tgz" + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.16.0.tgz", + "integrity": "sha1-+Q5g2ghikJ084JhzO105h8l8uN4=", + "requires": { + "chalk": "^1.1.0", + "esutils": "^2.0.2", + "js-tokens": "^2.0.0" + } }, "babel-compile": { "version": "2.0.0", - "from": "babel-compile@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/babel-compile/-/babel-compile-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/babel-compile/-/babel-compile-2.0.0.tgz", + "integrity": "sha1-JwRg2Fzah1iqXGMWWzZaa8RMmXY=", + "requires": { + "babel-core": "^6.7.0", + "commander": "^2.8.1", + "fs-walk": "0.0.1", + "lodash": "^4.11.1", + "mkdirp": "^0.5.1", + "rimraf": "^2.4.3" + } }, "babel-core": { "version": "6.17.0", - "from": "babel-core@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.17.0.tgz" + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.17.0.tgz", + "integrity": "sha1-bEV2RH30eeJB5YyAfkvH2k239CU=", + "requires": { + "babel-code-frame": "^6.16.0", + "babel-generator": "^6.17.0", + "babel-helpers": "^6.16.0", + "babel-messages": "^6.8.0", + "babel-register": "^6.16.0", + "babel-runtime": "^6.9.1", + "babel-template": "^6.16.0", + "babel-traverse": "^6.16.0", + "babel-types": "^6.16.0", + "babylon": "^6.11.0", + "convert-source-map": "^1.1.0", + "debug": "^2.1.1", + "json5": "^0.4.0", + "lodash": "^4.2.0", + "minimatch": "^3.0.2", + "path-exists": "^1.0.0", + "path-is-absolute": "^1.0.0", + "private": "^0.1.6", + "shebang-regex": "^1.0.0", + "slash": "^1.0.0", + "source-map": "^0.5.0" + } }, "babel-generator": { "version": "6.17.0", - "from": "babel-generator@>=6.17.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.17.0.tgz" + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.17.0.tgz", + "integrity": "sha1-uJTjgIvu94APJVBjW/4CS2ImzzM=", + "requires": { + "babel-messages": "^6.8.0", + "babel-runtime": "^6.9.0", + "babel-types": "^6.16.0", + "detect-indent": "^3.0.1", + "jsesc": "^1.3.0", + "lodash": "^4.2.0", + "source-map": "^0.5.0" + } }, "babel-helper-call-delegate": { "version": "6.8.0", - "from": "babel-helper-call-delegate@>=6.8.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.8.0.tgz", + "integrity": "sha1-nSg+dIZ3m2sEgYZKEbNx6lwB+mQ=", + "requires": { + "babel-helper-hoist-variables": "^6.8.0", + "babel-runtime": "^6.0.0", + "babel-traverse": "^6.8.0", + "babel-types": "^6.8.0" + } }, "babel-helper-define-map": { "version": "6.9.0", - "from": "babel-helper-define-map@>=6.9.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.9.0.tgz" + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.9.0.tgz", + "integrity": "sha1-Zin5sqfljhjoN5pX0eb7spaZAvs=", + "requires": { + "babel-helper-function-name": "^6.8.0", + "babel-runtime": "^6.9.0", + "babel-types": "^6.9.0", + "lodash": "^4.2.0" + } }, "babel-helper-function-name": { "version": "6.8.0", - "from": "babel-helper-function-name@>=6.8.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.8.0.tgz", + "integrity": "sha1-oDNroUUmoHXN9QL8UtP+hLEvejQ=", + "requires": { + "babel-helper-get-function-arity": "^6.8.0", + "babel-runtime": "^6.0.0", + "babel-template": "^6.8.0", + "babel-traverse": "^6.8.0", + "babel-types": "^6.8.0" + } }, "babel-helper-get-function-arity": { "version": "6.8.0", - "from": "babel-helper-get-function-arity@>=6.8.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.8.0.tgz", + "integrity": "sha1-iCdsJL0lHN9vYbb4n3RfSGztkq8=", + "requires": { + "babel-runtime": "^6.0.0", + "babel-types": "^6.8.0" + } }, "babel-helper-hoist-variables": { "version": "6.8.0", - "from": "babel-helper-hoist-variables@>=6.8.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.8.0.tgz", + "integrity": "sha1-iwdm3AJuqepCO8KzTmZaTac3Oq8=", + "requires": { + "babel-runtime": "^6.0.0", + "babel-types": "^6.8.0" + } }, "babel-helper-optimise-call-expression": { "version": "6.8.0", - "from": "babel-helper-optimise-call-expression@>=6.8.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.8.0.tgz", + "integrity": "sha1-QXVijpyJ/DYXSQTycHDynThWfwY=", + "requires": { + "babel-runtime": "^6.0.0", + "babel-types": "^6.8.0" + } }, "babel-helper-regex": { "version": "6.9.0", - "from": "babel-helper-regex@>=6.8.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.9.0.tgz" + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.9.0.tgz", + "integrity": "sha1-x0Jl/eGA/5oWc1/uBeY8rbngsFc=", + "requires": { + "babel-runtime": "^6.9.0", + "babel-types": "^6.9.0", + "lodash": "^4.2.0" + } }, "babel-helper-remap-async-to-generator": { "version": "6.16.2", - "from": "babel-helper-remap-async-to-generator@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.16.2.tgz" + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.16.2.tgz", + "integrity": "sha1-JDFb3oMmxgAi3AU8zoTP441yS4I=", + "requires": { + "babel-helper-function-name": "^6.8.0", + "babel-runtime": "^6.0.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.16.0", + "babel-types": "^6.16.0" + } }, "babel-helper-replace-supers": { "version": "6.16.0", - "from": "babel-helper-replace-supers@>=6.14.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.16.0.tgz" + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.16.0.tgz", + "integrity": "sha1-Icl2I8x+QwhVdT8lJ0ASJiajnms=", + "requires": { + "babel-helper-optimise-call-expression": "^6.8.0", + "babel-messages": "^6.8.0", + "babel-runtime": "^6.0.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.16.0", + "babel-types": "^6.16.0" + } }, "babel-helpers": { "version": "6.16.0", - "from": "babel-helpers@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.16.0.tgz" + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.16.0.tgz", + "integrity": "sha1-EJXsENmSeUYFU+Z+s+7plz04Z+M=", + "requires": { + "babel-runtime": "^6.0.0", + "babel-template": "^6.16.0" + } }, "babel-messages": { "version": "6.8.0", - "from": "babel-messages@>=6.8.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.8.0.tgz", + "integrity": "sha1-v1BHNsqWfm1l7wrbWipflHyODrk=", + "requires": { + "babel-runtime": "^6.0.0" + } }, "babel-plugin-check-es2015-constants": { "version": "6.8.0", - "from": "babel-plugin-check-es2015-constants@>=6.3.13 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.8.0.tgz", + "integrity": "sha1-2/Akwy7Te/2o3uHnbaAjhqjSb+c=", + "requires": { + "babel-runtime": "^6.0.0" + } }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", - "from": "babel-plugin-syntax-async-functions@>=6.8.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" }, "babel-plugin-transform-async-to-generator": { "version": "6.16.0", - "from": "babel-plugin-transform-async-to-generator@>=6.8.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.16.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.16.0.tgz", + "integrity": "sha1-Gew2yxSGtZ+fRorfpCzhOQjKKZk=", + "requires": { + "babel-helper-remap-async-to-generator": "^6.16.0", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.0.0" + } }, "babel-plugin-transform-es2015-arrow-functions": { "version": "6.8.0", - "from": "babel-plugin-transform-es2015-arrow-functions@>=6.3.13 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.8.0.tgz", + "integrity": "sha1-W2Ovwxgb3JqMTUgbWk8/fX/vPZ0=", + "requires": { + "babel-runtime": "^6.0.0" + } }, "babel-plugin-transform-es2015-block-scoped-functions": { "version": "6.8.0", - "from": "babel-plugin-transform-es2015-block-scoped-functions@>=6.3.13 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.8.0.tgz", + "integrity": "sha1-7ZXWKcS1pxriloK5mPcNmDPrNm0=", + "requires": { + "babel-runtime": "^6.0.0" + } }, "babel-plugin-transform-es2015-block-scoping": { "version": "6.15.0", - "from": "babel-plugin-transform-es2015-block-scoping@>=6.14.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.15.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.15.0.tgz", + "integrity": "sha1-W0Q8oUK+jR22qMKuQvUZWLZrcPY=", + "requires": { + "babel-runtime": "^6.9.0", + "babel-template": "^6.15.0", + "babel-traverse": "^6.15.0", + "babel-types": "^6.15.0", + "lodash": "^4.2.0" + } }, "babel-plugin-transform-es2015-classes": { "version": "6.14.0", - "from": "babel-plugin-transform-es2015-classes@>=6.14.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.14.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.14.0.tgz", + "integrity": "sha1-h9UUnukftHWSJAn5r1srpdHjkoc=", + "requires": { + "babel-helper-define-map": "^6.9.0", + "babel-helper-function-name": "^6.8.0", + "babel-helper-optimise-call-expression": "^6.8.0", + "babel-helper-replace-supers": "^6.14.0", + "babel-messages": "^6.8.0", + "babel-runtime": "^6.9.0", + "babel-template": "^6.14.0", + "babel-traverse": "^6.14.0", + "babel-types": "^6.14.0" + } }, "babel-plugin-transform-es2015-computed-properties": { "version": "6.8.0", - "from": "babel-plugin-transform-es2015-computed-properties@>=6.3.13 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.8.0.tgz", + "integrity": "sha1-9RAQ/WGzvXtrYKX9/TB7t6UnmHA=", + "requires": { + "babel-helper-define-map": "^6.8.0", + "babel-runtime": "^6.0.0", + "babel-template": "^6.8.0" + } }, "babel-plugin-transform-es2015-destructuring": { "version": "6.16.0", - "from": "babel-plugin-transform-es2015-destructuring@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.16.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.16.0.tgz", + "integrity": "sha1-BQ/ghm9dU7NgYu4QzfW/5k+Slic=", + "requires": { + "babel-runtime": "^6.9.0" + } }, "babel-plugin-transform-es2015-duplicate-keys": { "version": "6.8.0", - "from": "babel-plugin-transform-es2015-duplicate-keys@>=6.6.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.8.0.tgz", + "integrity": "sha1-/Y9/cXH8EIzBxwwxZLnxWoHCX30=", + "requires": { + "babel-runtime": "^6.0.0", + "babel-types": "^6.8.0" + } }, "babel-plugin-transform-es2015-for-of": { "version": "6.8.0", - "from": "babel-plugin-transform-es2015-for-of@>=6.6.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.8.0.tgz", + "integrity": "sha1-gu2hObpCcN2hNcPsGx8oE/pi8jw=", + "requires": { + "babel-runtime": "^6.0.0" + } }, "babel-plugin-transform-es2015-function-name": { "version": "6.9.0", - "from": "babel-plugin-transform-es2015-function-name@>=6.9.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.9.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.9.0.tgz", + "integrity": "sha1-jBNbF9vQZOW7pW7FEbqu4vyoJxk=", + "requires": { + "babel-helper-function-name": "^6.8.0", + "babel-runtime": "^6.9.0", + "babel-types": "^6.9.0" + } }, "babel-plugin-transform-es2015-literals": { "version": "6.8.0", - "from": "babel-plugin-transform-es2015-literals@>=6.3.13 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.8.0.tgz", + "integrity": "sha1-UKouXHlY/CqyXXTsEX4MyY8EZGg=", + "requires": { + "babel-runtime": "^6.0.0" + } }, "babel-plugin-transform-es2015-modules-amd": { "version": "6.8.0", - "from": "babel-plugin-transform-es2015-modules-amd@>=6.8.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.8.0.tgz", + "integrity": "sha1-JdlUqgvwQDH8RtKo5iMLsau95KM=", + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.8.0", + "babel-runtime": "^6.0.0", + "babel-template": "^6.8.0" + } }, "babel-plugin-transform-es2015-modules-commonjs": { "version": "6.16.0", - "from": "babel-plugin-transform-es2015-modules-commonjs@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.16.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.16.0.tgz", + "integrity": "sha1-CjS0R7yIrRpwmIttGZzKbQuWyJI=", + "requires": { + "babel-plugin-transform-strict-mode": "^6.8.0", + "babel-runtime": "^6.0.0", + "babel-template": "^6.16.0", + "babel-types": "^6.16.0" + } }, "babel-plugin-transform-es2015-modules-systemjs": { "version": "6.14.0", - "from": "babel-plugin-transform-es2015-modules-systemjs@>=6.14.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.14.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.14.0.tgz", + "integrity": "sha1-xRm1xz4yOI5nnJse30Gy/CPcMwM=", + "requires": { + "babel-helper-hoist-variables": "^6.8.0", + "babel-runtime": "^6.11.6", + "babel-template": "^6.14.0" + } }, "babel-plugin-transform-es2015-modules-umd": { "version": "6.12.0", - "from": "babel-plugin-transform-es2015-modules-umd@>=6.12.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.12.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.12.0.tgz", + "integrity": "sha1-XXNVnrSSZnde0oHEC+iKQhvTcaM=", + "requires": { + "babel-plugin-transform-es2015-modules-amd": "^6.8.0", + "babel-runtime": "^6.0.0", + "babel-template": "^6.8.0" + } }, "babel-plugin-transform-es2015-object-super": { "version": "6.8.0", - "from": "babel-plugin-transform-es2015-object-super@>=6.3.13 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.8.0.tgz", + "integrity": "sha1-G4WHQKWkQAiHwj3P9vTVbupKJMU=", + "requires": { + "babel-helper-replace-supers": "^6.8.0", + "babel-runtime": "^6.0.0" + } }, "babel-plugin-transform-es2015-parameters": { "version": "6.17.0", - "from": "babel-plugin-transform-es2015-parameters@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.17.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.17.0.tgz", + "integrity": "sha1-4G0wzviX9GrbRzRwe74Sig1CfVg=", + "requires": { + "babel-helper-call-delegate": "^6.8.0", + "babel-helper-get-function-arity": "^6.8.0", + "babel-runtime": "^6.9.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.16.0", + "babel-types": "^6.16.0" + } }, "babel-plugin-transform-es2015-shorthand-properties": { "version": "6.8.0", - "from": "babel-plugin-transform-es2015-shorthand-properties@>=6.3.13 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.8.0.tgz", + "integrity": "sha1-8KTF/UcWMKzzM8LZnD1ne/CVIUk=", + "requires": { + "babel-runtime": "^6.0.0", + "babel-types": "^6.8.0" + } }, "babel-plugin-transform-es2015-spread": { "version": "6.8.0", - "from": "babel-plugin-transform-es2015-spread@>=6.3.13 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.8.0.tgz", + "integrity": "sha1-Ahf3N+O4IfpaZp8YfG7VkgXwXpw=", + "requires": { + "babel-runtime": "^6.0.0" + } }, "babel-plugin-transform-es2015-sticky-regex": { "version": "6.8.0", - "from": "babel-plugin-transform-es2015-sticky-regex@>=6.3.13 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.8.0.tgz", + "integrity": "sha1-5z0wCkQKNdXGT1wqNE3CNuPfR74=", + "requires": { + "babel-helper-regex": "^6.8.0", + "babel-runtime": "^6.0.0", + "babel-types": "^6.8.0" + } }, "babel-plugin-transform-es2015-template-literals": { "version": "6.8.0", - "from": "babel-plugin-transform-es2015-template-literals@>=6.6.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.8.0.tgz", + "integrity": "sha1-huuHbQosY12k7ASLT33p38iX5ms=", + "requires": { + "babel-runtime": "^6.0.0" + } }, "babel-plugin-transform-es2015-typeof-symbol": { "version": "6.8.0", - "from": "babel-plugin-transform-es2015-typeof-symbol@>=6.6.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.8.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.8.0.tgz", + "integrity": "sha1-hMKesSGTckgJVaAg/vemXETzBTM=", + "requires": { + "babel-runtime": "^6.0.0" + } }, "babel-plugin-transform-es2015-unicode-regex": { "version": "6.11.0", - "from": "babel-plugin-transform-es2015-unicode-regex@>=6.3.13 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.11.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.11.0.tgz", + "integrity": "sha1-YpjOq6rYjVCj9POS2N6ZcmD27yw=", + "requires": { + "babel-helper-regex": "^6.8.0", + "babel-runtime": "^6.0.0", + "regexpu-core": "^2.0.0" + } }, "babel-plugin-transform-regenerator": { "version": "6.16.1", - "from": "babel-plugin-transform-regenerator@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.16.1.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.16.1.tgz", + "integrity": "sha1-p13msEihQVSq4UsBInVsW+05L1k=", + "requires": { + "babel-runtime": "^6.9.0", + "babel-types": "^6.16.0", + "private": "~0.1.5" + } }, "babel-plugin-transform-runtime": { "version": "6.15.0", - "from": "babel-plugin-transform-runtime@>=6.9.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.15.0.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.15.0.tgz", + "integrity": "sha1-PXW02Umtga8VdXAnOEb7Wa6w1Xw=", + "requires": { + "babel-runtime": "^6.9.0" + } }, "babel-plugin-transform-strict-mode": { "version": "6.11.3", - "from": "babel-plugin-transform-strict-mode@>=6.8.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.11.3.tgz" + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.11.3.tgz", + "integrity": "sha1-GDdBMlEmvH7Jz0wPwlfT58pa/UA=", + "requires": { + "babel-runtime": "^6.0.0", + "babel-types": "^6.8.0" + } }, "babel-polyfill": { "version": "6.16.0", - "from": "babel-polyfill@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.16.0.tgz" + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.16.0.tgz", + "integrity": "sha1-LUUCHfh+JqN0ttTRqcZZZNF/JCI=", + "requires": { + "babel-runtime": "^6.9.1", + "core-js": "^2.4.0", + "regenerator-runtime": "^0.9.5" + } }, "babel-preset-es2015": { "version": "6.16.0", - "from": "babel-preset-es2015@>=6.9.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.16.0.tgz" + "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.16.0.tgz", + "integrity": "sha1-Wazs0e++uvSPiUBIQPL+eMTSrVw=", + "requires": { + "babel-plugin-check-es2015-constants": "^6.3.13", + "babel-plugin-transform-es2015-arrow-functions": "^6.3.13", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.3.13", + "babel-plugin-transform-es2015-block-scoping": "^6.14.0", + "babel-plugin-transform-es2015-classes": "^6.14.0", + "babel-plugin-transform-es2015-computed-properties": "^6.3.13", + "babel-plugin-transform-es2015-destructuring": "^6.16.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.6.0", + "babel-plugin-transform-es2015-for-of": "^6.6.0", + "babel-plugin-transform-es2015-function-name": "^6.9.0", + "babel-plugin-transform-es2015-literals": "^6.3.13", + "babel-plugin-transform-es2015-modules-amd": "^6.8.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.16.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.14.0", + "babel-plugin-transform-es2015-modules-umd": "^6.12.0", + "babel-plugin-transform-es2015-object-super": "^6.3.13", + "babel-plugin-transform-es2015-parameters": "^6.16.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.3.13", + "babel-plugin-transform-es2015-spread": "^6.3.13", + "babel-plugin-transform-es2015-sticky-regex": "^6.3.13", + "babel-plugin-transform-es2015-template-literals": "^6.6.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.6.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.3.13", + "babel-plugin-transform-regenerator": "^6.16.0" + } }, "babel-preset-taskcluster": { "version": "3.0.0", - "from": "babel-preset-taskcluster@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/babel-preset-taskcluster/-/babel-preset-taskcluster-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/babel-preset-taskcluster/-/babel-preset-taskcluster-3.0.0.tgz", + "integrity": "sha1-QEfdaJJzFmGkjgRVHMBazTp3TFc=", + "requires": { + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-plugin-transform-async-to-generator": "^6.8.0", + "babel-plugin-transform-runtime": "^6.9.0", + "babel-plugin-transform-strict-mode": "^6.8.0", + "babel-preset-es2015": "^6.9.0", + "babel-runtime": "^6.9.2" + } }, "babel-register": { "version": "6.16.3", - "from": "babel-register@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.16.3.tgz" + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.16.3.tgz", + "integrity": "sha1-ewwMp7/euRiLpMJ+X8t1maSXxiQ=", + "requires": { + "babel-core": "^6.16.0", + "babel-runtime": "^6.11.6", + "core-js": "^2.4.0", + "home-or-tmp": "^1.0.0", + "lodash": "^4.2.0", + "mkdirp": "^0.5.1", + "path-exists": "^1.0.0", + "source-map-support": "^0.4.2" + } }, "babel-runtime": { "version": "6.11.6", - "from": "babel-runtime@>=6.11.6 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.11.6.tgz" + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.11.6.tgz", + "integrity": "sha1-bbcH/vLUnEm/o8tk79tDa1GLgiI=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.9.5" + } }, "babel-template": { "version": "6.16.0", - "from": "babel-template@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.16.0.tgz" + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.16.0.tgz", + "integrity": "sha1-4UndGp8Do1+BfdvE0EgZiOfryMo=", + "requires": { + "babel-runtime": "^6.9.0", + "babel-traverse": "^6.16.0", + "babel-types": "^6.16.0", + "babylon": "^6.11.0", + "lodash": "^4.2.0" + } }, "babel-traverse": { "version": "6.16.0", - "from": "babel-traverse@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.16.0.tgz" + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.16.0.tgz", + "integrity": "sha1-+6ha4f1NEH3pzgAxScxX9TvvDE8=", + "requires": { + "babel-code-frame": "^6.16.0", + "babel-messages": "^6.8.0", + "babel-runtime": "^6.9.0", + "babel-types": "^6.16.0", + "babylon": "^6.11.0", + "debug": "^2.2.0", + "globals": "^8.3.0", + "invariant": "^2.2.0", + "lodash": "^4.2.0" + } }, "babel-types": { "version": "6.16.0", - "from": "babel-types@>=6.16.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.16.0.tgz" + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.16.0.tgz", + "integrity": "sha1-ccyh2+Uzd2YiXFwZMHHo68vP/P4=", + "requires": { + "babel-runtime": "^6.9.1", + "esutils": "^2.0.2", + "lodash": "^4.2.0", + "to-fast-properties": "^1.0.1" + } }, "babylon": { "version": "6.11.6", - "from": "babylon@>=6.11.0 <7.0.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.11.6.tgz" + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.11.6.tgz", + "integrity": "sha1-VtxS5iSIKEHH/glSV/vLSlu2GuE=" }, "balanced-match": { "version": "0.4.2", - "from": "balanced-match@>=0.4.1 <0.5.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz" + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" }, "bcrypt-pbkdf": { "version": "1.0.0", - "from": "bcrypt-pbkdf@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz", + "integrity": "sha1-PKdrhSQccXC/fZcD57mqdGMAQNQ=", + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } }, "bin-version": { "version": "1.0.4", - "from": "bin-version@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-1.0.4.tgz" + "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-1.0.4.tgz", + "integrity": "sha1-nrSY7m/Xb3q5p8FgQ2+JV5Q1144=", + "requires": { + "find-versions": "^1.0.0" + } }, "bin-version-check": { "version": "2.1.0", - "from": "bin-version-check@>=2.1.0 <3.0.0", - "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-2.1.0.tgz", + "integrity": "sha1-5OXfKQuQaffRETJAMe/BP90RpbA=", + "requires": { + "bin-version": "^1.0.0", + "minimist": "^1.1.0", + "semver": "^4.0.3", + "semver-truncate": "^1.0.0" + } }, "binary-extensions": { "version": "1.7.0", - "from": "binary-extensions@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.7.0.tgz" + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.7.0.tgz", + "integrity": "sha1-bBYQ2xY6v7NO3+QvpCM0Oh4BGF0=", + "optional": true }, "bitsyntax": { "version": "0.0.4", - "from": "bitsyntax@>=0.0.4 <0.1.0", - "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz" + "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.0.4.tgz", + "integrity": "sha1-6xDMb4K4xJDj6FaY8H6D1G4MuoI=", + "requires": { + "buffer-more-ints": "0.0.2" + } }, "bl": { "version": "1.1.2", - "from": "bl@>=1.1.2 <1.2.0", "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", + "requires": { + "readable-stream": "~2.0.5" + }, "dependencies": { "readable-stream": { "version": "2.0.6", - "from": "readable-stream@>=2.0.5 <2.1.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz" + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } } } }, "boom": { "version": "2.10.1", - "from": "boom@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "requires": { + "hoek": "2.x.x" + } }, "brace-expansion": { "version": "1.1.6", - "from": "brace-expansion@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz" + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", + "integrity": "sha1-cZfX6qm4fmSDkOph/GbIRCdCDfk=", + "requires": { + "balanced-match": "^0.4.1", + "concat-map": "0.0.1" + } }, "braces": { "version": "1.8.5", - "from": "braces@>=1.8.2 <2.0.0", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz" + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "optional": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } }, "buffer-more-ints": { "version": "0.0.2", - "from": "buffer-more-ints@0.0.2", - "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz" + "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-0.0.2.tgz", + "integrity": "sha1-JrOIXRD6E9t/wBquOquHAZngEkw=" }, "buffer-shims": { "version": "1.0.0", - "from": "buffer-shims@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "optional": true }, "builtin-modules": { "version": "1.1.1", - "from": "builtin-modules@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" }, "camelcase": { "version": "2.1.1", - "from": "camelcase@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz" + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" }, "camelcase-keys": { "version": "2.1.0", - "from": "camelcase-keys@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } }, "caseless": { "version": "0.11.0", - "from": "caseless@>=0.11.0 <0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz" + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=" }, "chalk": { "version": "1.1.1", - "from": "chalk@1.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.1.tgz", + "integrity": "sha1-UJr7ZwZudJn36zU1x3RFdyri0Bk=", + "requires": { + "ansi-styles": "^2.1.0", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } }, "chokidar": { "version": "1.6.0", - "from": "chokidar@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.6.0.tgz" + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.6.0.tgz", + "integrity": "sha1-kMMq1IApAddxPeUy3ChOlqY60Fg=", + "optional": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } }, "combined-stream": { "version": "1.0.5", - "from": "combined-stream@>=1.0.5 <1.1.0", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz" + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "~1.0.0" + } }, "commander": { "version": "2.9.0", - "from": "commander@>=2.8.1 <3.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz" + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "requires": { + "graceful-readlink": ">= 1.0.0" + } }, "component-emitter": { "version": "1.2.1", - "from": "component-emitter@>=1.2.0 <1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" }, "concat-map": { "version": "0.0.1", - "from": "concat-map@0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "convert-source-map": { "version": "1.3.0", - "from": "convert-source-map@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.3.0.tgz" + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.3.0.tgz", + "integrity": "sha1-6fPpxuJyjvwmdmlqcOs4L3MQamc=" }, "cookiejar": { "version": "2.0.6", - "from": "cookiejar@2.0.6", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.0.6.tgz" + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.0.6.tgz", + "integrity": "sha1-Cr81atANHFohnYjURRgEbdAmrP4=" }, "core-js": { "version": "2.4.1", - "from": "core-js@>=2.4.0 <3.0.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz" + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", + "integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=" }, "core-util-is": { "version": "1.0.2", - "from": "core-util-is@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cryptiles": { "version": "2.0.5", - "from": "cryptiles@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz" + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "requires": { + "boom": "2.x.x" + } }, "currently-unhandled": { "version": "0.4.1", - "from": "currently-unhandled@>=0.4.1 <0.5.0", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz" + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "requires": { + "array-find-index": "^1.0.1" + } }, "dashdash": { "version": "1.14.0", - "from": "dashdash@>=1.12.0 <2.0.0", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz", + "integrity": "sha1-KeSGxUGL8PNWA0qZPVFoajPoQUE=", + "requires": { + "assert-plus": "^1.0.0" + }, "dependencies": { "assert-plus": { "version": "1.0.0", - "from": "assert-plus@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" } } }, "debug": { "version": "2.2.0", - "from": "debug@>=2.1.1 <3.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } }, "decamelize": { "version": "1.2.0", - "from": "decamelize@>=1.1.2 <2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "delayed-stream": { "version": "1.0.0", - "from": "delayed-stream@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "detect-indent": { "version": "3.0.1", - "from": "detect-indent@>=3.0.1 <4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-3.0.1.tgz", + "integrity": "sha1-ncXl3bzu+DJXZLlFGwK8bVQIT3U=", + "requires": { + "get-stdin": "^4.0.1", + "minimist": "^1.1.0", + "repeating": "^1.1.0" + } }, "ecc-jsbn": { "version": "0.1.1", - "from": "ecc-jsbn@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "~0.1.0" + } }, "error-ex": { "version": "1.3.0", - "from": "error-ex@>=1.2.0 <2.0.0", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.0.tgz" + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.0.tgz", + "integrity": "sha1-5ntD8+gsluo6WE/+4Ln8MyXYAtk=", + "requires": { + "is-arrayish": "^0.2.1" + } }, "escape-string-regexp": { "version": "1.0.5", - "from": "escape-string-regexp@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "esprima": { "version": "2.7.3", - "from": "esprima@>=2.6.0 <3.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz" + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" }, "esutils": { "version": "2.0.2", - "from": "esutils@>=2.0.2 <3.0.0", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz" + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" }, "eventsource": { "version": "0.1.6", - "from": "eventsource@>=0.1.6 <0.2.0", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz" + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz", + "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", + "optional": true, + "requires": { + "original": ">=0.0.5" + } }, "expand-brackets": { "version": "0.1.5", - "from": "expand-brackets@>=0.1.4 <0.2.0", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz" + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "optional": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } }, "expand-range": { "version": "1.8.2", - "from": "expand-range@>=1.8.1 <2.0.0", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz" + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "optional": true, + "requires": { + "fill-range": "^2.1.0" + } }, "extend": { "version": "3.0.0", - "from": "extend@>=3.0.0 <3.1.0", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", + "integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ=" }, "extglob": { "version": "0.3.2", - "from": "extglob@>=0.3.1 <0.4.0", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz" + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "optional": true, + "requires": { + "is-extglob": "^1.0.0" + } }, "extsprintf": { "version": "1.0.2", - "from": "extsprintf@1.0.2", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=" }, "faye-websocket": { "version": "0.11.0", - "from": "faye-websocket@>=0.11.0 <0.12.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.0.tgz" + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.0.tgz", + "integrity": "sha1-2czw54nn23JddLxId9I6pClyrFA=", + "optional": true, + "requires": { + "websocket-driver": ">=0.5.1" + } }, "filename-regex": { "version": "2.0.0", - "from": "filename-regex@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.0.tgz", + "integrity": "sha1-mW4+gEebmLmJfxWopYs9CE6SZ3U=", + "optional": true }, "fill-range": { "version": "2.2.3", - "from": "fill-range@>=2.1.0 <3.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz" + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "optional": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^1.1.3", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } }, "find-up": { "version": "1.1.2", - "from": "find-up@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, "dependencies": { "path-exists": { "version": "2.1.0", - "from": "path-exists@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } } } }, "find-versions": { "version": "1.2.1", - "from": "find-versions@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-1.2.1.tgz", + "integrity": "sha1-y96fEuOFdaCvG+G5osXV/Y8Ya2I=", + "requires": { + "array-uniq": "^1.0.0", + "get-stdin": "^4.0.1", + "meow": "^3.5.0", + "semver-regex": "^1.0.0" + } }, "flatmap": { "version": "0.0.3", - "from": "flatmap@0.0.3", - "resolved": "https://registry.npmjs.org/flatmap/-/flatmap-0.0.3.tgz" + "resolved": "https://registry.npmjs.org/flatmap/-/flatmap-0.0.3.tgz", + "integrity": "sha1-Hxik2TgVLUlZZfnJWNkjqy3WabQ=" }, "for-in": { "version": "0.1.6", - "from": "for-in@>=0.1.5 <0.2.0", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.6.tgz" + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.6.tgz", + "integrity": "sha1-yfluib+tGKVFr17D7TUqHZ5bTcg=", + "optional": true }, "for-own": { "version": "0.1.4", - "from": "for-own@>=0.1.3 <0.2.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.4.tgz" + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.4.tgz", + "integrity": "sha1-AUm0GjkIjHUV9R6+HBOG1F+TUHI=", + "optional": true, + "requires": { + "for-in": "^0.1.5" + } }, "forever-agent": { "version": "0.6.1", - "from": "forever-agent@>=0.6.1 <0.7.0", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { "version": "2.0.0", - "from": "form-data@>=2.0.0 <2.1.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", + "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.11" + } }, "formidable": { "version": "1.0.17", - "from": "formidable@>=1.0.14 <1.1.0", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.17.tgz" + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.17.tgz", + "integrity": "sha1-71SRSQ+UM7cF+qdyScmQKa40hVk=" }, "fs-readdir-recursive": { "version": "0.1.2", - "from": "fs-readdir-recursive@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-0.1.2.tgz" + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-0.1.2.tgz", + "integrity": "sha1-MVtPuMHKW4xH3v7zGdBz2tNWgFk=" }, "fs-walk": { "version": "0.0.1", - "from": "fs-walk@0.0.1", - "resolved": "https://registry.npmjs.org/fs-walk/-/fs-walk-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/fs-walk/-/fs-walk-0.0.1.tgz", + "integrity": "sha1-9/yRw64e6tB8mYvF0N1B8tvr0zU=", + "requires": { + "async": "*" + } }, "fs.realpath": { "version": "1.0.0", - "from": "fs.realpath@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", + "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "needle": { + "version": "2.2.4", + "bundled": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.3", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.5", + "bundled": true, + "optional": true + }, + "npm-packlist": { + "version": "1.2.0", + "bundled": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "optional": true + }, + "semver": { + "version": "5.6.0", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true + } + } }, "generate-function": { "version": "2.0.0", - "from": "generate-function@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=" }, "generate-object-property": { "version": "1.2.0", - "from": "generate-object-property@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "requires": { + "is-property": "^1.0.0" + } }, "get-stdin": { "version": "4.0.1", - "from": "get-stdin@>=4.0.1 <5.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz" + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" }, "getpass": { "version": "0.1.6", - "from": "getpass@>=0.1.1 <0.2.0", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", + "integrity": "sha1-KD/9n8ElaECHUxHBtg6MQBhxEOY=", + "requires": { + "assert-plus": "^1.0.0" + }, "dependencies": { "assert-plus": { "version": "1.0.0", - "from": "assert-plus@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" } } }, "glob": { "version": "5.0.15", - "from": "glob@>=5.0.5 <6.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz" + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "glob-base": { "version": "0.3.0", - "from": "glob-base@>=0.3.0 <0.4.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz" + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "optional": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + } }, "glob-parent": { "version": "2.0.0", - "from": "glob-parent@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "^2.0.0" + } }, "globals": { "version": "8.18.0", - "from": "globals@>=8.3.0 <9.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-8.18.0.tgz" + "resolved": "https://registry.npmjs.org/globals/-/globals-8.18.0.tgz", + "integrity": "sha1-k9SmK9ysOM+vr8R9awNHaMsP/LQ=" }, "graceful-fs": { "version": "4.1.9", - "from": "graceful-fs@>=4.1.2 <5.0.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.9.tgz" + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha1-uqy6N9GdEfnRRtNXi8mZWMN4fik=" }, "graceful-readlink": { "version": "1.0.1", - "from": "graceful-readlink@>=1.0.0", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" }, "har-validator": { "version": "2.0.6", - "from": "har-validator@>=2.0.6 <2.1.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz" + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "requires": { + "chalk": "^1.1.1", + "commander": "^2.9.0", + "is-my-json-valid": "^2.12.4", + "pinkie-promise": "^2.0.0" + } }, "has-ansi": { "version": "2.0.0", - "from": "has-ansi@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } }, "hawk": { "version": "3.1.3", - "from": "hawk@>=3.1.3 <3.2.0", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz" + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + } }, "hoek": { "version": "2.16.3", - "from": "hoek@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" }, "home-or-tmp": { "version": "1.0.0", - "from": "home-or-tmp@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-1.0.0.tgz", + "integrity": "sha1-S58eQIAMPlDGwn94FnavzOcfOYU=", + "requires": { + "os-tmpdir": "^1.0.1", + "user-home": "^1.1.1" + } }, "hosted-git-info": { "version": "2.1.5", - "from": "hosted-git-info@>=2.1.4 <3.0.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz" + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz", + "integrity": "sha1-C6gdkNouJas0ozLm7HeTbhWYEYs=" }, "http-signature": { "version": "1.1.1", - "from": "http-signature@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } }, "indent-string": { "version": "2.1.0", - "from": "indent-string@>=2.1.0 <3.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "requires": { + "repeating": "^2.0.0" + }, "dependencies": { "repeating": { "version": "2.0.1", - "from": "repeating@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "requires": { + "is-finite": "^1.0.0" + } } } }, "inflight": { "version": "1.0.6", - "from": "inflight@>=1.0.4 <2.0.0", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } }, "inherits": { "version": "2.0.3", - "from": "inherits@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "intersect": { "version": "1.0.1", - "from": "intersect@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/intersect/-/intersect-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/intersect/-/intersect-1.0.1.tgz", + "integrity": "sha1-MyZQ4QhU2MCsWMGSvcJ6i/fnoww=" }, "invariant": { "version": "2.2.1", - "from": "invariant@>=2.2.0 <3.0.0", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.1.tgz" + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.1.tgz", + "integrity": "sha1-sJcBBUdmjH4zcCjr6Bbr42yKjVQ=", + "requires": { + "loose-envify": "^1.0.0" + } }, "is-arrayish": { "version": "0.2.1", - "from": "is-arrayish@>=0.2.1 <0.3.0", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-binary-path": { "version": "1.0.1", - "from": "is-binary-path@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } }, "is-buffer": { "version": "1.1.4", - "from": "is-buffer@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.4.tgz" + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.4.tgz", + "integrity": "sha1-z8hszV3FpS+oBIkRHGkgxFfi2Ys=" }, "is-builtin-module": { "version": "1.0.0", - "from": "is-builtin-module@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "^1.0.0" + } }, "is-dotfile": { "version": "1.0.2", - "from": "is-dotfile@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz", + "integrity": "sha1-LBMjg/ORmfjtwmjKAbmwB9IFzE0=", + "optional": true }, "is-equal-shallow": { "version": "0.1.3", - "from": "is-equal-shallow@>=0.1.3 <0.2.0", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz" + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "optional": true, + "requires": { + "is-primitive": "^2.0.0" + } }, "is-extendable": { "version": "0.1.1", - "from": "is-extendable@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "optional": true }, "is-extglob": { "version": "1.0.0", - "from": "is-extglob@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" }, "is-finite": { "version": "1.0.2", - "from": "is-finite@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-glob": { "version": "2.0.1", - "from": "is-glob@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "^1.0.0" + } }, "is-my-json-valid": { "version": "2.15.0", - "from": "is-my-json-valid@>=2.12.4 <3.0.0", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz" + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz", + "integrity": "sha1-k27do8o8IR/ZjzstPgjaQ/eykVs=", + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + } }, "is-number": { "version": "2.1.0", - "from": "is-number@>=2.1.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "^3.0.2" + } }, "is-posix-bracket": { "version": "0.1.1", - "from": "is-posix-bracket@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "optional": true }, "is-primitive": { "version": "2.0.0", - "from": "is-primitive@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" }, "is-property": { "version": "1.0.2", - "from": "is-property@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" }, "is-typedarray": { "version": "1.0.0", - "from": "is-typedarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "is-utf8": { "version": "0.2.1", - "from": "is-utf8@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz" + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, "isarray": { "version": "1.0.0", - "from": "isarray@1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isobject": { "version": "2.1.0", - "from": "isobject@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "optional": true, + "requires": { + "isarray": "1.0.0" + } }, "isstream": { "version": "0.1.2", - "from": "isstream@>=0.1.2 <0.2.0", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "jodid25519": { "version": "1.0.2", - "from": "jodid25519@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", + "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", + "optional": true, + "requires": { + "jsbn": "~0.1.0" + } }, "js-tokens": { "version": "2.0.0", - "from": "js-tokens@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-2.0.0.tgz", + "integrity": "sha1-eZA/VWPud4zBFi5tzxoAJ8l/nLU=" }, "js-yaml": { "version": "3.6.1", - "from": "js-yaml@>=3.6.1 <4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz" + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", + "requires": { + "argparse": "^1.0.7", + "esprima": "^2.6.0" + } }, "jsbn": { "version": "0.1.0", - "from": "jsbn@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz" + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz", + "integrity": "sha1-ZQmH2g3XT06/WhE3eiqi0nPpff0=", + "optional": true }, "jsesc": { "version": "1.3.0", - "from": "jsesc@>=1.3.0 <2.0.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz" + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" }, "json-schema": { "version": "0.2.3", - "from": "json-schema@0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz" + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-stringify-safe": { "version": "5.0.1", - "from": "json-stringify-safe@>=5.0.1 <5.1.0", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json3": { "version": "3.3.2", - "from": "json3@>=3.3.2 <4.0.0", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz" + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "optional": true }, "json5": { "version": "0.4.0", - "from": "json5@>=0.4.0 <0.5.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.4.0.tgz" + "resolved": "https://registry.npmjs.org/json5/-/json5-0.4.0.tgz", + "integrity": "sha1-BUNS5MTIDIbAkjh31EneF2pzLI0=" }, "jsonpointer": { "version": "4.0.0", - "from": "jsonpointer@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.0.tgz" + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.0.tgz", + "integrity": "sha1-ZmHhYdL8RF8Z+YQwIxNDci4fy9U=" }, "jsprim": { "version": "1.3.1", - "from": "jsprim@>=1.2.2 <2.0.0", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz" + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz", + "integrity": "sha1-KnJW9wQSop7jZwqspiWZTE3P8lI=", + "requires": { + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + } }, "kind-of": { "version": "3.0.4", - "from": "kind-of@>=3.0.2 <4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.0.4.tgz" + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.0.4.tgz", + "integrity": "sha1-e47PGKThf4Jp1ztQHJ8jLJaIenQ=", + "requires": { + "is-buffer": "^1.0.2" + } }, "load-json-file": { "version": "1.1.0", - "from": "load-json-file@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } }, "lodash": { "version": "4.16.4", - "from": "lodash@>=4.2.0 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.16.4.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.16.4.tgz", + "integrity": "sha1-Ac4wa5utExnypVKGdPiCl663ASc=" }, "log-symbols": { "version": "1.0.2", - "from": "log-symbols@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "requires": { + "chalk": "^1.0.0" + } }, "loose-envify": { "version": "1.2.0", - "from": "loose-envify@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.2.0.tgz", + "integrity": "sha1-aaZarT3lQs9O4PT+dOjjPHCcyw8=", + "requires": { + "js-tokens": "^1.0.1" + }, "dependencies": { "js-tokens": { "version": "1.0.3", - "from": "js-tokens@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz", + "integrity": "sha1-FOVutoyPGpLEPVn1AU7CncIPKuE=" } } }, "loud-rejection": { "version": "1.6.0", - "from": "loud-rejection@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz" + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } }, "map-obj": { "version": "1.0.1", - "from": "map-obj@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" }, "meow": { "version": "3.7.0", - "from": "meow@>=3.5.0 <4.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz" + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } }, "merge": { "version": "1.2.0", - "from": "merge@>=1.2.0 <2.0.0", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", + "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=" }, "methods": { "version": "1.1.2", - "from": "methods@>=1.1.1 <1.2.0", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "micromatch": { "version": "2.3.11", - "from": "micromatch@>=2.1.5 <3.0.0", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz" + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "optional": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } }, "mime": { "version": "1.3.4", - "from": "mime@1.3.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" }, "mime-db": { "version": "1.24.0", - "from": "mime-db@>=1.24.0 <1.25.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.24.0.tgz" + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.24.0.tgz", + "integrity": "sha1-4tE/k58AFsbk6a0lqGUvEmxGfww=" }, "mime-types": { "version": "2.1.12", - "from": "mime-types@>=2.1.7 <2.2.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz" + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.12.tgz", + "integrity": "sha1-FSuiVndwIN1GY/VMLnvCY4HnFyk=", + "requires": { + "mime-db": "~1.24.0" + } }, "minimatch": { "version": "3.0.3", - "from": "minimatch@>=3.0.2 <4.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz" + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", + "requires": { + "brace-expansion": "^1.0.0" + } }, "minimist": { "version": "1.2.0", - "from": "minimist@>=1.2.0 <2.0.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "mkdirp": { "version": "0.5.1", - "from": "mkdirp@>=0.5.1 <0.6.0", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + }, "dependencies": { "minimist": { "version": "0.0.8", - "from": "minimist@0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" } } }, "ms": { "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + }, + "nan": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", + "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", + "optional": true }, "node-uuid": { "version": "1.4.7", - "from": "node-uuid@>=1.4.7 <1.5.0", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz" + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz", + "integrity": "sha1-baWhdmjEs91ZYjvaEc9/pMH2Cm8=" }, "normalize-package-data": { "version": "2.3.5", - "from": "normalize-package-data@>=2.3.4 <3.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz" + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz", + "integrity": "sha1-jZJPFClg4Xd+f/4XBUNjHMfLAt8=", + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } }, "normalize-path": { "version": "2.0.1", - "from": "normalize-path@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz", + "integrity": "sha1-R4hqwWYnYNQmG32XnSQXCdPOP3o=", + "optional": true }, "number-is-nan": { "version": "1.0.1", - "from": "number-is-nan@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "oauth-sign": { "version": "0.8.2", - "from": "oauth-sign@>=0.8.1 <0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz" + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" }, "object-assign": { "version": "4.1.0", - "from": "object-assign@>=4.0.1 <5.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz" + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", + "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=" }, "object.omit": { "version": "2.0.0", - "from": "object.omit@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.0.tgz", + "integrity": "sha1-hoWXMz1U5gZilAu0WGBd1q4S/pQ=", + "optional": true, + "requires": { + "for-own": "^0.1.3", + "is-extendable": "^0.1.1" + } }, "once": { "version": "1.4.0", - "from": "once@>=1.3.0 <2.0.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } }, "original": { "version": "1.0.0", - "from": "original@>=0.0.5", "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", + "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=", + "optional": true, + "requires": { + "url-parse": "1.0.x" + }, "dependencies": { "url-parse": { "version": "1.0.5", - "from": "url-parse@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz" + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz", + "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=", + "optional": true, + "requires": { + "querystringify": "0.0.x", + "requires-port": "1.0.x" + } } } }, "os-tmpdir": { "version": "1.0.2", - "from": "os-tmpdir@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "output-file-sync": { "version": "1.1.2", - "from": "output-file-sync@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "requires": { + "graceful-fs": "^4.1.4", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.0" + } }, "parse-glob": { "version": "3.0.4", - "from": "parse-glob@>=3.0.4 <4.0.0", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz" + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "optional": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + } }, "parse-json": { "version": "2.2.0", - "from": "parse-json@>=2.2.0 <3.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz" + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } }, "path-exists": { "version": "1.0.0", - "from": "path-exists@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", + "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=" }, "path-is-absolute": { "version": "1.0.1", - "from": "path-is-absolute@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-type": { "version": "1.1.0", - "from": "path-type@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } }, "pify": { "version": "2.3.0", - "from": "pify@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz" + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "pinkie": { "version": "2.0.4", - "from": "pinkie@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz" + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" }, "pinkie-promise": { "version": "2.0.1", - "from": "pinkie-promise@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } }, "preserve": { "version": "0.2.0", - "from": "preserve@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "optional": true }, "private": { "version": "0.1.6", - "from": "private@>=0.1.6 <0.2.0", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.6.tgz" + "resolved": "https://registry.npmjs.org/private/-/private-0.1.6.tgz", + "integrity": "sha1-VcapdtD5uvuZJIUTUP5HubX7t8E=" }, "process-nextick-args": { "version": "1.0.7", - "from": "process-nextick-args@>=1.0.6 <1.1.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" }, "promise": { "version": "6.1.0", - "from": "promise@>=6.1.0 <7.0.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz" + "resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz", + "integrity": "sha1-LOcp9rlLRcJoka0GAsXJDgTG7vY=", + "requires": { + "asap": "~1.0.0" + } }, "qs": { "version": "6.2.1", - "from": "qs@>=6.2.0 <6.3.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz" + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz", + "integrity": "sha1-zgPF/wk1vB2daanxTL0Y5WjWdiU=" }, "querystringify": { "version": "0.0.4", - "from": "querystringify@>=0.0.0 <0.1.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz" + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz", + "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=" }, "randomatic": { "version": "1.1.5", - "from": "randomatic@>=1.1.3 <2.0.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.5.tgz" + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.5.tgz", + "integrity": "sha1-Xp718tVzxnvSuBJK6QtRVuRXhAs=", + "optional": true, + "requires": { + "is-number": "^2.0.2", + "kind-of": "^3.0.2" + } }, "read-pkg": { "version": "1.1.0", - "from": "read-pkg@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } }, "read-pkg-up": { "version": "1.0.1", - "from": "read-pkg-up@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } }, "readable-stream": { "version": "2.1.5", - "from": "readable-stream@>=2.0.2 <3.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz" + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", + "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", + "optional": true, + "requires": { + "buffer-shims": "^1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } }, "readdirp": { "version": "2.1.0", - "from": "readdirp@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz" + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "optional": true, + "requires": { + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" + } }, "redent": { "version": "1.0.0", - "from": "redent@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } }, "reduce-component": { "version": "1.0.1", - "from": "reduce-component@1.0.1", - "resolved": "https://registry.npmjs.org/reduce-component/-/reduce-component-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/reduce-component/-/reduce-component-1.0.1.tgz", + "integrity": "sha1-4Mk1QsV0UhvqE98PlIjtgqt3xdo=" }, "regenerate": { "version": "1.3.1", - "from": "regenerate@>=1.2.1 <2.0.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.1.tgz" + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.1.tgz", + "integrity": "sha1-AwAgOl0v3PiRFtzoQnXQEfWQPzM=" }, "regenerator-runtime": { "version": "0.9.5", - "from": "regenerator-runtime@>=0.9.5 <0.10.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.5.tgz" + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.5.tgz", + "integrity": "sha1-QD1tQKS9/5wzDdk5Lcuy2ai7ofw=" }, "regex-cache": { "version": "0.4.3", - "from": "regex-cache@>=0.4.2 <0.5.0", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz" + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", + "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", + "optional": true, + "requires": { + "is-equal-shallow": "^0.1.3", + "is-primitive": "^2.0.0" + } }, "regexpu-core": { "version": "2.0.0", - "from": "regexpu-core@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } }, "regjsgen": { "version": "0.2.0", - "from": "regjsgen@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" }, "regjsparser": { "version": "0.1.5", - "from": "regjsparser@>=0.1.4 <0.2.0", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "requires": { + "jsesc": "~0.5.0" + }, "dependencies": { "jsesc": { "version": "0.5.0", - "from": "jsesc@>=0.5.0 <0.6.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" } } }, "repeat-element": { "version": "1.1.2", - "from": "repeat-element@>=1.1.2 <2.0.0", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz" + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" }, "repeat-string": { "version": "1.5.4", - "from": "repeat-string@>=1.5.2 <2.0.0", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.5.4.tgz" + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.5.4.tgz", + "integrity": "sha1-ZOwMkeD0tHX5DVtkNlHj5uW2wtU=", + "optional": true }, "repeating": { "version": "1.1.3", - "from": "repeating@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz" + "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", + "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=", + "requires": { + "is-finite": "^1.0.0" + } }, "request": { "version": "2.75.0", - "from": "request@>=2.65.0 <3.0.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.75.0.tgz" + "resolved": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", + "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "bl": "~1.1.2", + "caseless": "~0.11.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.0.0", + "har-validator": "~2.0.6", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "node-uuid": "~1.4.7", + "oauth-sign": "~0.8.1", + "qs": "~6.2.0", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "~0.4.1" + } }, "requires-port": { "version": "1.0.0", - "from": "requires-port@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, "rimraf": { "version": "2.5.4", - "from": "rimraf@>=2.4.3 <3.0.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", + "requires": { + "glob": "^7.0.5" + }, "dependencies": { "glob": { "version": "7.1.1", - "from": "glob@>=7.0.5 <8.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz" + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } } } }, "semver": { "version": "4.3.6", - "from": "semver@>=4.0.3 <5.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz" + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" }, "semver-regex": { "version": "1.0.0", - "from": "semver-regex@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", + "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=" }, "semver-truncate": { "version": "1.1.2", - "from": "semver-truncate@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-1.1.2.tgz", + "integrity": "sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g=", + "requires": { + "semver": "^5.3.0" + }, "dependencies": { "semver": { "version": "5.3.0", - "from": "semver@>=5.3.0 <6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" } } }, "set-immediate-shim": { "version": "1.0.1", - "from": "set-immediate-shim@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "optional": true }, "shebang-regex": { "version": "1.0.0", - "from": "shebang-regex@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, "signal-exit": { "version": "3.0.1", - "from": "signal-exit@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.1.tgz", + "integrity": "sha1-WkyISZK2OnrNm623iUw+6c/MrYE=" }, "slash": { "version": "1.0.0", - "from": "slash@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" }, "slugid": { "version": "1.1.0", - "from": "slugid@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/slugid/-/slugid-1.1.0.tgz" + "resolved": "https://registry.npmjs.org/slugid/-/slugid-1.1.0.tgz", + "integrity": "sha1-4J8AiZwJ9acFjtw23UnwRv1QqCo=", + "requires": { + "uuid": "^2.0.1" + } }, "sntp": { "version": "1.0.9", - "from": "sntp@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "requires": { + "hoek": "2.x.x" + } }, "sockjs-client": { "version": "1.1.1", - "from": "sockjs-client@>=1.0.3 <2.0.0", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.1.tgz", + "integrity": "sha1-KEhD6al4TXxHSxVxsyQPyp3aS7A=", + "optional": true, + "requires": { + "debug": "^2.2.0", + "eventsource": "~0.1.6", + "faye-websocket": "~0.11.0", + "inherits": "^2.0.1", + "json3": "^3.3.2", + "url-parse": "^1.1.1" + } }, "source-map": { "version": "0.5.6", - "from": "source-map@>=0.5.0 <0.6.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz" + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=" }, "source-map-support": { "version": "0.4.3", - "from": "source-map-support@>=0.4.2 <0.5.0", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.3.tgz" + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.3.tgz", + "integrity": "sha1-aTyDg9Q4mkVpSGmHwhl0TfxgFoU=", + "requires": { + "source-map": "^0.5.3" + } }, "spdx-correct": { "version": "1.0.2", - "from": "spdx-correct@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "requires": { + "spdx-license-ids": "^1.0.2" + } }, "spdx-expression-parse": { "version": "1.0.4", - "from": "spdx-expression-parse@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz" + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" }, "spdx-license-ids": { "version": "1.2.2", - "from": "spdx-license-ids@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz" + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" }, "sprintf-js": { "version": "1.0.3", - "from": "sprintf-js@>=1.0.2 <1.1.0", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.10.1", - "from": "sshpk@>=1.7.0 <2.0.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.10.1.tgz", + "integrity": "sha1-MOGl0ykkSXShr2FREznVla9mOLA=", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jodid25519": "^1.0.0", + "jsbn": "~0.1.0", + "tweetnacl": "~0.14.0" + }, "dependencies": { "assert-plus": { "version": "1.0.0", - "from": "assert-plus@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" } } }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, "stringstream": { "version": "0.0.5", - "from": "stringstream@>=0.0.4 <0.1.0", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz" + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" }, "strip-ansi": { "version": "3.0.1", - "from": "strip-ansi@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } }, "strip-bom": { "version": "2.0.0", - "from": "strip-bom@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } }, "strip-indent": { "version": "1.0.1", - "from": "strip-indent@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz" + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "requires": { + "get-stdin": "^4.0.1" + } }, "superagent": { "version": "1.7.2", - "from": "superagent@>=1.7.0 <1.8.0", "resolved": "https://registry.npmjs.org/superagent/-/superagent-1.7.2.tgz", + "integrity": "sha1-Zfnu1PU2EyDJ2HRBKrd7666ktXI=", + "requires": { + "component-emitter": "~1.2.0", + "cookiejar": "2.0.6", + "debug": "2", + "extend": "3.0.0", + "form-data": "0.2.0", + "formidable": "~1.0.14", + "methods": "~1.1.1", + "mime": "1.3.4", + "qs": "2.3.3", + "readable-stream": "1.0.27-1", + "reduce-component": "1.0.1" + }, "dependencies": { "async": { "version": "0.9.2", - "from": "async@>=0.9.0 <0.10.0", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz" + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" }, "combined-stream": { "version": "0.0.7", - "from": "combined-stream@>=0.0.4 <0.1.0", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz" + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "requires": { + "delayed-stream": "0.0.5" + } }, "delayed-stream": { "version": "0.0.5", - "from": "delayed-stream@0.0.5", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz" + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=" }, "form-data": { "version": "0.2.0", - "from": "form-data@0.2.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz", + "integrity": "sha1-Jvi8JtpkQOKZy9z7aQNcT3em5GY=", + "requires": { + "async": "~0.9.0", + "combined-stream": "~0.0.4", + "mime-types": "~2.0.3" + } }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, "mime-db": { "version": "1.12.0", - "from": "mime-db@>=1.12.0 <1.13.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz" + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz", + "integrity": "sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc=" }, "mime-types": { "version": "2.0.14", - "from": "mime-types@>=2.0.3 <2.1.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz" + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz", + "integrity": "sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY=", + "requires": { + "mime-db": "~1.12.0" + } }, "qs": { "version": "2.3.3", - "from": "qs@2.3.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz" + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=" }, "readable-stream": { "version": "1.0.27-1", - "from": "readable-stream@1.0.27-1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.27-1.tgz" + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.27-1.tgz", + "integrity": "sha1-a2eYPCA1fO/QfwFlABoW1xDZEHg=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } } } }, "superagent-hawk": { "version": "0.0.6", - "from": "superagent-hawk@>=0.0.6 <0.0.7", "resolved": "https://registry.npmjs.org/superagent-hawk/-/superagent-hawk-0.0.6.tgz", + "integrity": "sha1-DPtw4hVG46PpAtogiijt2WX4Las=", + "requires": { + "hawk": "~1.0.0", + "qs": "^0.6.6" + }, "dependencies": { "boom": { "version": "0.4.2", - "from": "boom@>=0.4.0 <0.5.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "requires": { + "hoek": "0.9.x" + } }, "cryptiles": { "version": "0.2.2", - "from": "cryptiles@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", + "requires": { + "boom": "0.4.x" + } }, "hawk": { "version": "1.0.0", - "from": "hawk@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", + "integrity": "sha1-uQuxaYByhUEdp//LjdJZhQLTtS0=", + "requires": { + "boom": "0.4.x", + "cryptiles": "0.2.x", + "hoek": "0.9.x", + "sntp": "0.2.x" + } }, "hoek": { "version": "0.9.1", - "from": "hoek@>=0.9.0 <0.10.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=" }, "qs": { "version": "0.6.6", - "from": "qs@>=0.6.6 <0.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz" + "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz", + "integrity": "sha1-bgFQmP9RlouKPIGQAdXyyJvEsQc=" }, "sntp": { "version": "0.2.4", - "from": "sntp@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", + "requires": { + "hoek": "0.9.x" + } } } }, "superagent-promise": { "version": "0.2.0", - "from": "superagent-promise@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/superagent-promise/-/superagent-promise-0.2.0.tgz" + "resolved": "https://registry.npmjs.org/superagent-promise/-/superagent-promise-0.2.0.tgz", + "integrity": "sha1-kcd/TLDJz0G+65F9it1pf20Vyuo=" }, "supports-color": { "version": "2.0.0", - "from": "supports-color@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, "taskcluster-client": { "version": "1.4.0", - "from": "taskcluster-client@>=1.2.1 <2.0.0", "resolved": "https://registry.npmjs.org/taskcluster-client/-/taskcluster-client-1.4.0.tgz", + "integrity": "sha1-Q4xjfIe0ZK52JxBHs7wgFmFjJkg=", + "requires": { + "amqplib": "^0.4.1", + "debug": "^2.1.3", + "hawk": "^2.3.1", + "lodash": "^3.6.0", + "promise": "^6.1.0", + "slugid": "^1.1.0", + "sockjs-client": "^1.0.3", + "superagent": "~1.7.0", + "superagent-hawk": "^0.0.6", + "superagent-promise": "^0.2.0", + "url-join": "^0.0.1" + }, "dependencies": { "hawk": { "version": "2.3.1", - "from": "hawk@>=2.3.1 <3.0.0", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-2.3.1.tgz" + "resolved": "https://registry.npmjs.org/hawk/-/hawk-2.3.1.tgz", + "integrity": "sha1-HnMc45RH+h0PbXB/e87r7A/R7B8=", + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + } }, "lodash": { "version": "3.10.1", - "from": "lodash@>=3.6.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" } } }, "to-fast-properties": { "version": "1.0.2", - "from": "to-fast-properties@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.2.tgz", + "integrity": "sha1-8/XAw7pymafvmUJ+RGMyV63kMyA=" }, "tough-cookie": { "version": "2.3.1", - "from": "tough-cookie@>=2.3.0 <2.4.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.1.tgz" + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.1.tgz", + "integrity": "sha1-mcd9+7fYBCSeiimdTLD9gf7wg/0=" }, "trim-newlines": { "version": "1.0.0", - "from": "trim-newlines@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" }, "tunnel-agent": { "version": "0.4.3", - "from": "tunnel-agent@>=0.4.1 <0.5.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz" + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=" }, "tweetnacl": { "version": "0.14.3", - "from": "tweetnacl@>=0.14.0 <0.15.0", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.3.tgz" + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.3.tgz", + "integrity": "sha1-PaOC9nDyXe1417PReSEZvKC3Ey0=", + "optional": true }, "url-join": { "version": "0.0.1", - "from": "url-join@>=0.0.1 <0.0.2", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz" + "resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz", + "integrity": "sha1-HbSK1CLTQCRpqH99l73r/k+x48g=" }, "url-parse": { "version": "1.1.6", - "from": "url-parse@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.1.6.tgz" + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.1.6.tgz", + "integrity": "sha1-q4/1rqE4gHGWElXiI2FHxSyl/Eg=", + "optional": true, + "requires": { + "querystringify": "0.0.x", + "requires-port": "1.0.x" + } }, "user-home": { "version": "1.1.1", - "from": "user-home@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz" + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=" }, "util-deprecate": { "version": "1.0.2", - "from": "util-deprecate@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { "version": "2.0.3", - "from": "uuid@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz" + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=" }, "v8flags": { "version": "2.0.11", - "from": "v8flags@>=2.0.10 <3.0.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.0.11.tgz" + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.0.11.tgz", + "integrity": "sha1-vKjzDw1tYGEswsAGQeaWLUKuaIE=", + "requires": { + "user-home": "^1.1.1" + } }, "validate-npm-package-license": { "version": "3.0.1", - "from": "validate-npm-package-license@>=3.0.1 <4.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz" + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "requires": { + "spdx-correct": "~1.0.0", + "spdx-expression-parse": "~1.0.0" + } }, "verror": { "version": "1.3.6", - "from": "verror@1.3.6", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz" + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", + "requires": { + "extsprintf": "1.0.2" + } }, "websocket-driver": { "version": "0.6.5", - "from": "websocket-driver@>=0.5.1", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz" + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", + "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", + "optional": true, + "requires": { + "websocket-extensions": ">=0.1.1" + } }, "websocket-extensions": { "version": "0.1.1", - "from": "websocket-extensions@>=0.1.1", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz" + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz", + "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec=", + "optional": true }, "when": { "version": "3.6.4", - "from": "when@>=3.6.2 <3.7.0", - "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz" + "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz", + "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=" }, "wrappy": { "version": "1.0.2", - "from": "wrappy@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "xtend": { "version": "4.0.1", - "from": "xtend@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" } } } diff --git a/security/nss/automation/taskcluster/graph/src/index.js b/security/nss/automation/taskcluster/graph/src/index.js index 4153e1b18f..0a3a241173 100644 --- a/security/nss/automation/taskcluster/graph/src/index.js +++ b/security/nss/automation/taskcluster/graph/src/index.js @@ -5,10 +5,17 @@ import * as try_syntax from "./try_syntax"; import extend from "./extend"; -// Init try syntax filter. -if (process.env.TC_PROJECT == "nss-try") { - try_syntax.initFilter(); -} +const main = async () => { + // Init try syntax filter. + if (process.env.TC_PROJECT == "nss-try") { + await try_syntax.initFilter(); + } -// Extend the task graph. -extend().catch(console.error); + // Extend the task graph. + await extend(); +}; + +main().catch(err => { + console.error(err); + process.exit(1); +}); diff --git a/security/nss/automation/taskcluster/graph/src/try_syntax.js b/security/nss/automation/taskcluster/graph/src/try_syntax.js index f1772a658c..b974745073 100644 --- a/security/nss/automation/taskcluster/graph/src/try_syntax.js +++ b/security/nss/automation/taskcluster/graph/src/try_syntax.js @@ -5,6 +5,10 @@ import * as queue from "./queue"; import intersect from "intersect"; import parse_args from "minimist"; +import util from "util"; +import child_process from 'child_process'; + +let execFile = util.promisify(child_process.execFile); function parseOptions(opts) { opts = parse_args(opts.split(/\s+/), { @@ -154,8 +158,13 @@ function filter(opts) { } } -export function initFilter() { - let comment = process.env.TC_COMMENT || ""; +async function getCommitComment() { + const res = await execFile('hg', ['log', '-r', '.', '-T', '{desc}']); + return res.stdout; +}; + +export async function initFilter() { + let comment = await getCommitComment(); // Check for try syntax in changeset comment. let match = comment.match(/^\s*try:\s*(.*)\s*$/); diff --git a/security/nss/build.sh b/security/nss/build.sh index 4c6d513cd4..66f5981818 100644 --- a/security/nss/build.sh +++ b/security/nss/build.sh @@ -103,6 +103,7 @@ while [ $# -gt 0 ]; do --enable-fips) gyp_params+=(-Ddisable_fips=0) ;; --enable-libpkix) gyp_params+=(-Ddisable_libpkix=0) ;; --mozpkix-only) gyp_params+=(-Dmozpkix_only=1 -Ddisable_tests=1 -Dsign_libs=0) ;; + -D*) gyp_params+=("$1") ;; *) show_help; exit 2 ;; esac shift diff --git a/security/nss/cmd/atob/atob.c b/security/nss/cmd/atob/atob.c index 115b0e9a0f..3e15ceadb0 100644 --- a/security/nss/cmd/atob/atob.c +++ b/security/nss/cmd/atob/atob.c @@ -105,7 +105,6 @@ Usage(char *progName) "-i input"); fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n", "-o output"); - exit(-1); } int @@ -113,12 +112,12 @@ main(int argc, char **argv) { char *progName; SECStatus rv; - FILE *inFile, *outFile; - PLOptState *optstate; + FILE *inFile = NULL, *outFile = NULL; + PRBool closeIn = PR_TRUE, closeOut = PR_TRUE; + PLOptState *optstate = NULL; PLOptStatus status; + int exitCode = -1; - inFile = 0; - outFile = 0; progName = strrchr(argv[0], '/'); progName = progName ? progName + 1 : argv[0]; @@ -129,6 +128,7 @@ main(int argc, char **argv) case '?': case 'h': Usage(progName); + goto loser; break; case 'i': @@ -136,7 +136,7 @@ main(int argc, char **argv) if (!inFile) { fprintf(stderr, "%s: unable to open \"%s\" for reading\n", progName, optstate->value); - return -1; + goto loser; } break; @@ -145,13 +145,15 @@ main(int argc, char **argv) if (!outFile) { fprintf(stderr, "%s: unable to open \"%s\" for writing\n", progName, optstate->value); - return -1; + goto loser; } break; } } - if (!inFile) + if (!inFile) { inFile = stdin; + closeIn = PR_FALSE; + } if (!outFile) { #if defined(WIN32) int smrv = _setmode(_fileno(stdout), _O_BINARY); @@ -159,16 +161,28 @@ main(int argc, char **argv) fprintf(stderr, "%s: Cannot change stdout to binary mode. Use -o option instead.\n", progName); - return smrv; + goto loser; } #endif outFile = stdout; + closeOut = PR_FALSE; } rv = decode_file(outFile, inFile); if (rv != SECSuccess) { fprintf(stderr, "%s: lossage: error=%d errno=%d\n", progName, PORT_GetError(), errno); - return -1; + goto loser; } - return 0; + exitCode = 0; +loser: + if (optstate) { + PL_DestroyOptState(optstate); + } + if (inFile && closeIn) { + fclose(inFile); + } + if (outFile && closeOut) { + fclose(outFile); + } + return exitCode; } diff --git a/security/nss/cmd/btoa/btoa.c b/security/nss/cmd/btoa/btoa.c index 2a5e6d4c65..434afa81fd 100644 --- a/security/nss/cmd/btoa/btoa.c +++ b/security/nss/cmd/btoa/btoa.c @@ -99,7 +99,6 @@ Usage(char *progName) "-w suffix"); fprintf(stderr, "%-20s (use \"c\" as a shortcut for suffix CERTIFICATE)\n", ""); - exit(-1); } int @@ -107,13 +106,13 @@ main(int argc, char **argv) { char *progName; SECStatus rv; - FILE *inFile, *outFile; - PLOptState *optstate; + FILE *inFile = NULL, *outFile = NULL; + PRBool closeIn = PR_TRUE, closeOut = PR_TRUE; + PLOptState *optstate = NULL; PLOptStatus status; char *suffix = NULL; + int exitCode = -1; - inFile = 0; - outFile = 0; progName = strrchr(argv[0], '/'); if (!progName) progName = strrchr(argv[0], '\\'); @@ -125,6 +124,7 @@ main(int argc, char **argv) switch (optstate->option) { default: Usage(progName); + goto loser; break; case 'i': @@ -132,7 +132,7 @@ main(int argc, char **argv) if (!inFile) { fprintf(stderr, "%s: unable to open \"%s\" for reading\n", progName, optstate->value); - return -1; + goto loser; } break; @@ -141,7 +141,7 @@ main(int argc, char **argv) if (!outFile) { fprintf(stderr, "%s: unable to open \"%s\" for writing\n", progName, optstate->value); - return -1; + goto loser; } break; @@ -166,10 +166,11 @@ main(int argc, char **argv) fprintf(stderr, "%s: Cannot change stdin to binary mode. Use -i option instead.\n", progName); - return smrv; + goto loser; } #endif inFile = stdin; + closeIn = PR_FALSE; } if (!outFile) { #if defined(WIN32) @@ -182,10 +183,11 @@ main(int argc, char **argv) fprintf(stderr, "%s: Cannot change stdout to binary mode. Use -o option instead.\n", progName); - return smrv; + goto loser; } #endif outFile = stdout; + closeOut = PR_FALSE; } if (suffix) { fprintf(outFile, "-----BEGIN %s-----\n", suffix); @@ -194,10 +196,21 @@ main(int argc, char **argv) if (rv != SECSuccess) { fprintf(stderr, "%s: lossage: error=%d errno=%d\n", progName, PORT_GetError(), errno); - return -1; + goto loser; } if (suffix) { fprintf(outFile, "-----END %s-----\n", suffix); } - return 0; + exitCode = 0; +loser: + if (optstate) { + PL_DestroyOptState(optstate); + } + if (inFile && closeIn) { + fclose(inFile); + } + if (outFile && closeOut) { + fclose(outFile); + } + return exitCode; } diff --git a/security/nss/cmd/manifest.mn b/security/nss/cmd/manifest.mn index be53d3c4eb..695177c9dc 100644 --- a/security/nss/cmd/manifest.mn +++ b/security/nss/cmd/manifest.mn @@ -56,6 +56,7 @@ NSS_SRCDIRS = \ p7sign \ p7verify \ pk12util \ + pk11importtest \ pk11ectest \ pk11gcmtest \ pk11mode \ diff --git a/security/nss/cmd/pk11importtest/Makefile b/security/nss/cmd/pk11importtest/Makefile new file mode 100644 index 0000000000..fc8358d5ad --- /dev/null +++ b/security/nss/cmd/pk11importtest/Makefile @@ -0,0 +1,43 @@ +#! gmake +# +# 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/. + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include ../platlibs.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + +include ../platrules.mk diff --git a/security/nss/cmd/pk11importtest/manifest.mn b/security/nss/cmd/pk11importtest/manifest.mn new file mode 100644 index 0000000000..5c40a8108a --- /dev/null +++ b/security/nss/cmd/pk11importtest/manifest.mn @@ -0,0 +1,15 @@ +# 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/. + +CORE_DEPTH = ../.. + +MODULE = nss + +CSRCS = pk11importtest.c \ + $(NULL) + +REQUIRES = seccmd + +PROGRAM = pk11importtest + diff --git a/security/nss/cmd/pk11importtest/pk11importtest.c b/security/nss/cmd/pk11importtest/pk11importtest.c new file mode 100644 index 0000000000..b2f4890609 --- /dev/null +++ b/security/nss/cmd/pk11importtest/pk11importtest.c @@ -0,0 +1,406 @@ +/* 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/. */ + +#include "secutil.h" +#include "secmod.h" +#include "cert.h" +#include "secoid.h" +#include "nss.h" +#include "pk11pub.h" +#include "pk11pqg.h" + +/* NSPR 2.0 header files */ +#include "prinit.h" +#include "prprf.h" +#include "prsystem.h" +#include "prmem.h" +/* Portable layer header files */ +#include "plstr.h" + +SECOidData * +getCurveFromString(char *curve_name) +{ + SECOidTag tag = SEC_OID_SECG_EC_SECP256R1; + + if (PORT_Strcasecmp(curve_name, "NISTP256") == 0) { + } else if (PORT_Strcasecmp(curve_name, "NISTP384") == 0) { + tag = SEC_OID_SECG_EC_SECP384R1; + } else if (PORT_Strcasecmp(curve_name, "NISTP521") == 0) { + tag = SEC_OID_SECG_EC_SECP521R1; + } else if (PORT_Strcasecmp(curve_name, "Curve25519") == 0) { + tag = SEC_OID_CURVE25519; + } + return SECOID_FindOIDByTag(tag); +} + +void +dumpItem(const char *label, const SECItem *item) +{ + int i; + printf("%s = [%d bytes] {", label, item->len); + for (i = 0; i < item->len; i++) { + if ((i & 0xf) == 0) + printf("\n "); + else + printf(", "); + printf("%02x", item->data[i]); + } + printf("};\n"); +} + +SECStatus +handleEncryptedPrivateImportTest(char *progName, PK11SlotInfo *slot, + char *testname, CK_MECHANISM_TYPE genMech, void *params, void *pwArgs) +{ + SECStatus rv = SECSuccess; + SECItem privID = { 0 }; + SECItem pubID = { 0 }; + SECItem pubValue = { 0 }; + SECItem pbePwItem = { 0 }; + SECItem nickname = { 0 }; + SECItem token = { 0 }; + SECKEYPublicKey *pubKey = NULL; + SECKEYPrivateKey *privKey = NULL; + PK11GenericObject *objs = NULL; + PK11GenericObject *obj = NULL; + SECKEYEncryptedPrivateKeyInfo *epki = NULL; + PRBool keyFound = 0; + KeyType keyType; + + fprintf(stderr, "Testing %s PrivateKeyImport ***********************\n", + testname); + + /* generate a temp key */ + privKey = PK11_GenerateKeyPair(slot, genMech, params, &pubKey, + PR_FALSE, PR_TRUE, pwArgs); + if (privKey == NULL) { + SECU_PrintError(progName, "PK11_GenerateKeyPair Failed"); + goto cleanup; + } + + /* wrap the temp key */ + pbePwItem.data = (unsigned char *)"pw"; + pbePwItem.len = 2; + epki = PK11_ExportEncryptedPrivKeyInfo(slot, SEC_OID_AES_256_CBC, + &pbePwItem, privKey, 1, NULL); + if (epki == NULL) { + SECU_PrintError(progName, "PK11_ExportEncryptedPrivKeyInfo Failed"); + goto cleanup; + } + + /* Save the public value, which we will need on import */ + keyType = pubKey->keyType; + switch (keyType) { + case rsaKey: + SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.rsa.modulus); + break; + case dhKey: + SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.dh.publicValue); + break; + case dsaKey: + SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.dsa.publicValue); + break; + case ecKey: + SECITEM_CopyItem(NULL, &pubValue, &pubKey->u.ec.publicValue); + break; + default: + fprintf(stderr, "Unknown keytype = %d\n", keyType); + goto cleanup; + } + if (pubValue.data == NULL) { + SECU_PrintError(progName, "Unable to allocate memory"); + goto cleanup; + } + dumpItem("pubValue", &pubValue); + + /* when Asymetric keys represent session keys, those session keys are + * destroyed when we destroy the Asymetric key representations */ + SECKEY_DestroyPublicKey(pubKey); + pubKey = NULL; + SECKEY_DestroyPrivateKey(privKey); + privKey = NULL; + + /* unwrap the temp key as a perm */ + nickname.data = (unsigned char *)"testKey"; + nickname.len = sizeof("testKey"); + rv = PK11_ImportEncryptedPrivateKeyInfoAndReturnKey( + slot, epki, &pbePwItem, &nickname, &pubValue, + PR_TRUE, PR_TRUE, keyType, 0, &privKey, NULL); + if (rv != SECSuccess) { + SECU_PrintError(progName, "PK11_ImportEncryptedPrivateKeyInfo Failed"); + goto cleanup; + } + + /* verify the public key exists */ + rv = PK11_ReadRawAttribute(PK11_TypePrivKey, privKey, CKA_ID, &privID); + if (rv != SECSuccess) { + SECU_PrintError(progName, + "Couldn't read CKA_ID from pub key, checking next key"); + goto cleanup; + } + dumpItem("privKey CKA_ID", &privID); + objs = PK11_FindGenericObjects(slot, CKO_PUBLIC_KEY); + for (obj = objs; obj; obj = PK11_GetNextGenericObject(obj)) { + rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_ID, &pubID); + if (rv != SECSuccess) { + SECU_PrintError(progName, + "Couldn't read CKA_ID from object, checking next key"); + continue; + } + dumpItem("pubKey CKA_ID", &pubID); + if (!SECITEM_ItemsAreEqual(&privID, &pubID)) { + fprintf(stderr, + "CKA_ID does not match priv key, checking next key\n"); + SECITEM_FreeItem(&pubID, PR_FALSE); + continue; + } + SECITEM_FreeItem(&pubID, PR_FALSE); + rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, CKA_TOKEN, &token); + if (rv == SECSuccess) { + if (token.len == 1) { + keyFound = token.data[0]; + } + SECITEM_FreeItem(&token, PR_FALSE); + } + if (keyFound) { + printf("matching public key found\n"); + break; + } + printf("Matching key was not a token key, checking next key\n"); + } + +cleanup: + if (objs) { + PK11_DestroyGenericObjects(objs); + } + SECITEM_FreeItem(&pubValue, PR_FALSE); + SECITEM_FreeItem(&privID, PR_FALSE); + PORT_FreeArena(epki->arena, PR_TRUE); + SECKEY_DestroyPublicKey(pubKey); + SECKEY_DestroyPrivateKey(privKey); + fprintf(stderr, "%s PrivateKeyImport %s ***********************\n", + testname, keyFound ? "PASSED" : "FAILED"); + return keyFound ? SECSuccess : SECFailure; +} + +static const char *const usageInfo[] = { + "pk11import - test PK11_PrivateKeyImport()" + "Options:", + " -d certdir directory containing cert database", + " -k keysize size of the rsa, dh, and dsa key to test (default 1024)", + " -C ecc_curve ecc curve (default )", + " -f pwFile file to fetch the password from", + " -p pwString password", + " -r skip rsa test", + " -D skip dsa test", + " -h skip dh test", + " -e skip ec test", +}; +static int nUsageInfo = sizeof(usageInfo) / sizeof(char *); + +static void +Usage(char *progName, FILE *outFile) +{ + int i; + fprintf(outFile, "Usage: %s [ commands ] options\n", progName); + for (i = 0; i < nUsageInfo; i++) + fprintf(outFile, "%s\n", usageInfo[i]); + exit(-1); +} + +enum { + opt_CertDir, + opt_KeySize, + opt_ECCurve, + opt_PWFile, + opt_PWString, + opt_NoRSA, + opt_NoDSA, + opt_NoEC, + opt_NoDH +}; + +static secuCommandFlag options[] = + { + { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE }, + { /* opt_KeySize */ 'k', PR_TRUE, 0, PR_FALSE }, + { /* opt_ECCurve */ 'C', PR_TRUE, 0, PR_FALSE }, + { /* opt_PWFile */ 'f', PR_TRUE, 0, PR_FALSE }, + { /* opt_PWString */ 'p', PR_TRUE, 0, PR_FALSE }, + { /* opt_NORSA */ 'r', PR_TRUE, 0, PR_FALSE }, + { /* opt_NoDSA */ 'D', PR_TRUE, 0, PR_FALSE }, + { /* opt_NoDH */ 'h', PR_TRUE, 0, PR_FALSE }, + { /* opt_NoEC */ 'e', PR_TRUE, 0, PR_FALSE }, + }; + +int +main(int argc, char **argv) +{ + char *progName; + SECStatus rv; + secuCommand args; + PK11SlotInfo *slot = NULL; + PRBool failed = PR_FALSE; + secuPWData pwArgs = { PW_NONE, 0 }; + PRBool doRSA = PR_TRUE; + PRBool doDSA = PR_TRUE; + PRBool doDH = PR_FALSE; /* NSS currently can't export wrapped DH keys */ + PRBool doEC = PR_TRUE; + PQGParams *pqgParams = NULL; + int keySize; + + args.numCommands = 0; + args.numOptions = sizeof(options) / sizeof(secuCommandFlag); + args.commands = NULL; + args.options = options; + +#ifdef XP_PC + progName = strrchr(argv[0], '\\'); +#else + progName = strrchr(argv[0], '/'); +#endif + progName = progName ? progName + 1 : argv[0]; + + rv = SECU_ParseCommandLine(argc, argv, progName, &args); + if (SECSuccess != rv) { + Usage(progName, stderr); + } + + /* Set the certdb directory (default is ~/.netscape) */ + rv = NSS_InitReadWrite(SECU_ConfigDirectory(args.options[opt_CertDir].arg)); + if (rv != SECSuccess) { + SECU_PrintPRandOSError(progName); + return 255; + } + PK11_SetPasswordFunc(SECU_GetModulePassword); + + /* below here, goto cleanup */ + SECU_RegisterDynamicOids(); + + /* handle the arguments */ + if (args.options[opt_PWFile].arg) { + pwArgs.source = PW_FROMFILE; + pwArgs.data = args.options[opt_PWFile].arg; + } + if (args.options[opt_PWString].arg) { + pwArgs.source = PW_PLAINTEXT; + pwArgs.data = args.options[opt_PWString].arg; + } + if (args.options[opt_NoRSA].activated) { + doRSA = PR_FALSE; + } + if (args.options[opt_NoDSA].activated) { + doDSA = PR_FALSE; + } + if (args.options[opt_NoDH].activated) { + doDH = PR_FALSE; + } + if (args.options[opt_NoEC].activated) { + doEC = PR_FALSE; + } + + slot = PK11_GetInternalKeySlot(); + if (slot == NULL) { + SECU_PrintError(progName, "Couldn't find the internal key slot\n"); + return 255; + } + rv = PK11_Authenticate(slot, PR_TRUE, &pwArgs); + if (rv != SECSuccess) { + SECU_PrintError(progName, "Failed to log into slot"); + PK11_FreeSlot(slot); + return 255; + } + + keySize = 1024; + if (args.options[opt_KeySize].activated && + args.options[opt_KeySize].arg) { + keySize = atoi(args.options[opt_KeySize].arg); + } + + if (doDSA || doDH) { + PQGVerify *pqgVfy; + rv = PK11_PQG_ParamGenV2(keySize, 0, keySize / 16, &pqgParams, &pqgVfy); + if (rv == SECSuccess) { + PK11_PQG_DestroyVerify(pqgVfy); + } else { + SECU_PrintError(progName, + "PK11_PQG_ParamGenV2 failed, can't test DH or DSA"); + doDSA = doDH = PR_FALSE; + failed = PR_TRUE; + } + } + + if (doRSA) { + PK11RSAGenParams rsaParams; + rsaParams.keySizeInBits = keySize; + rsaParams.pe = 0x010001; + rv = handleEncryptedPrivateImportTest(progName, slot, "RSA", + CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams, &pwArgs); + if (rv != SECSuccess) { + fprintf(stderr, "RSA Import Failed!\n"); + failed = PR_TRUE; + } + } + if (doDSA) { + rv = handleEncryptedPrivateImportTest(progName, slot, "DSA", + CKM_DSA_KEY_PAIR_GEN, pqgParams, &pwArgs); + if (rv != SECSuccess) { + fprintf(stderr, "DSA Import Failed!\n"); + failed = PR_TRUE; + } + } + if (doDH) { + SECKEYDHParams dhParams; + dhParams.prime = pqgParams->prime; + dhParams.base = pqgParams->base; + rv = handleEncryptedPrivateImportTest(progName, slot, "DH", + CKM_DH_PKCS_KEY_PAIR_GEN, &dhParams, &pwArgs); + if (rv != SECSuccess) { + fprintf(stderr, "DH Import Failed!\n"); + failed = PR_TRUE; + } + } + if (doEC) { + SECKEYECParams ecParams; + SECOidData *curve = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1); + if (args.options[opt_ECCurve].activated && + args.options[opt_ECCurve].arg) { + curve = getCurveFromString(args.options[opt_ECCurve].arg); + } + ecParams.data = PORT_Alloc(curve->oid.len + 2); + if (ecParams.data == NULL) { + rv = SECFailure; + goto ec_failed; + } + ecParams.data[0] = SEC_ASN1_OBJECT_ID; + ecParams.data[1] = (unsigned char)curve->oid.len; + PORT_Memcpy(&ecParams.data[2], curve->oid.data, curve->oid.len); + ecParams.len = curve->oid.len + 2; + rv = handleEncryptedPrivateImportTest(progName, slot, "ECC", + CKM_EC_KEY_PAIR_GEN, &ecParams, &pwArgs); + PORT_Free(ecParams.data); + ec_failed: + if (rv != SECSuccess) { + fprintf(stderr, "ECC Import Failed!\n"); + failed = PR_TRUE; + } + } + + if (pqgParams) { + PK11_PQG_DestroyParams(pqgParams); + } + + if (slot) { + PK11_FreeSlot(slot); + } + + rv = NSS_Shutdown(); + if (rv != SECSuccess) { + fprintf(stderr, "Shutdown failed\n"); + SECU_PrintPRandOSError(progName); + return 255; + } + + return failed ? 1 : 0; +} diff --git a/security/nss/cmd/pk11importtest/pk11importtest.gyp b/security/nss/cmd/pk11importtest/pk11importtest.gyp new file mode 100644 index 0000000000..4fce059621 --- /dev/null +++ b/security/nss/cmd/pk11importtest/pk11importtest.gyp @@ -0,0 +1,25 @@ +# 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/. +{ + 'includes': [ + '../../coreconf/config.gypi', + '../../cmd/platlibs.gypi' + ], + 'targets': [ + { + 'target_name': 'pk11importtest', + 'type': 'executable', + 'sources': [ + 'pk11importtest.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:dbm_exports', + '<(DEPTH)/exports.gyp:nss_exports' + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/cmd/strsclnt/strsclnt.c b/security/nss/cmd/strsclnt/strsclnt.c index bba53efac6..099b7bf5ea 100644 --- a/security/nss/cmd/strsclnt/strsclnt.c +++ b/security/nss/cmd/strsclnt/strsclnt.c @@ -121,6 +121,9 @@ static PRBool enableCertStatus = PR_FALSE; PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT; +static const SSLSignatureScheme *enabledSigSchemes = NULL; +static unsigned int enabledSigSchemeCount = 0; + char *progName; secuPWData pwdata = { PW_NONE, 0 }; @@ -143,7 +146,8 @@ Usage(void) "Usage: %s [-n nickname] [-p port] [-d dbdir] [-c connections]\n" " [-BDNovqs] [-f filename] [-N | -P percentage]\n" " [-w dbpasswd] [-C cipher(s)] [-t threads] [-W pwfile]\n" - " [-V [min-version]:[max-version]] [-a sniHostName] hostname\n" + " [-V [min-version]:[max-version]] [-a sniHostName]\n" + " [-J signatureschemes] hostname\n" " where -v means verbose\n" " -o flag is interpreted as follows:\n" " 1 -o means override the result of server certificate validation.\n" @@ -161,7 +165,17 @@ Usage(void) " -T enable the cert_status extension (OCSP stapling)\n" " -u enable TLS Session Ticket extension\n" " -z enable compression\n" - " -g enable false start\n", + " -g enable false start\n" + " -J enable signature schemes\n" + " This takes a comma separated list of signature schemes in preference\n" + " order.\n" + " Possible values are:\n" + " rsa_pkcs1_sha1, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512,\n" + " ecdsa_sha1, ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384,\n" + " ecdsa_secp521r1_sha512,\n" + " rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512,\n" + " rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512,\n" + " dsa_sha1, dsa_sha256, dsa_sha384, dsa_sha512\n", progName); exit(1); } @@ -1158,6 +1172,14 @@ client_main( errExit("error setting SSL/TLS version range "); } + if (enabledSigSchemes) { + rv = SSL_SignatureSchemePrefSet(model_sock, enabledSigSchemes, + enabledSigSchemeCount); + if (rv < 0) { + errExit("SSL_SignatureSchemePrefSet"); + } + } + if (bigBuf.data) { /* doing FDX */ rv = SSL_OptionSet(model_sock, SSL_ENABLE_FDX, 1); if (rv < 0) { @@ -1316,7 +1338,7 @@ main(int argc, char **argv) /* XXX: 'B' was used in the past but removed in 3.28, * please leave some time before resuing it. */ optstate = PL_CreateOptState(argc, argv, - "C:DNP:TUV:W:a:c:d:f:gin:op:qst:uvw:z"); + "C:DJ:NP:TUV:W:a:c:d:f:gin:op:qst:uvw:z"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case 'C': @@ -1330,6 +1352,15 @@ main(int argc, char **argv) case 'I': /* reserved for OCSP multi-stapling */ break; + case 'J': + rv = parseSigSchemeList(optstate->value, &enabledSigSchemes, &enabledSigSchemeCount); + if (rv != SECSuccess) { + PL_DestroyOptState(optstate); + fprintf(stderr, "Bad signature scheme specified.\n"); + Usage(); + } + break; + case 'N': NoReuse = 1; break; @@ -1516,6 +1547,8 @@ main(int argc, char **argv) PL_strfree(hostName); + PORT_Free((SSLSignatureScheme *)enabledSigSchemes); + /* some final stats. */ printf( "strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n" diff --git a/security/nss/coreconf/config.gypi b/security/nss/coreconf/config.gypi index ba1b0c8c56..761393d541 100644 --- a/security/nss/coreconf/config.gypi +++ b/security/nss/coreconf/config.gypi @@ -94,6 +94,7 @@ 'disable_libpkix%': 1, 'disable_werror%': 0, 'mozilla_client%': 0, + 'comm_client%': 0, 'moz_fold_libs%': 0, 'moz_folded_library_name%': '', 'sanitizer_flags%': 0, diff --git a/security/nss/cpputil/nss_scoped_ptrs.h b/security/nss/cpputil/nss_scoped_ptrs.h index 03979f2c58..450e787af5 100644 --- a/security/nss/cpputil/nss_scoped_ptrs.h +++ b/security/nss/cpputil/nss_scoped_ptrs.h @@ -11,6 +11,7 @@ #include "cert.h" #include "keyhi.h" #include "p12.h" +#include "pk11pqg.h" #include "pk11pub.h" #include "pkcs11uri.h" @@ -41,6 +42,7 @@ struct ScopedDelete { void operator()(PLArenaPool* arena) { PORT_FreeArena(arena, PR_FALSE); } void operator()(PK11Context* context) { PK11_DestroyContext(context, true); } void operator()(PK11GenericObject* obj) { PK11_DestroyGenericObject(obj); } + void operator()(PQGParams* pqg) { PK11_PQG_DestroyParams(pqg); } void operator()(SEC_PKCS12DecoderContext* dcx) { SEC_PKCS12DecoderFinish(dcx); } @@ -66,6 +68,7 @@ SCOPED(CERTName); SCOPED(CERTSubjectPublicKeyInfo); SCOPED(PK11SlotInfo); SCOPED(PK11SymKey); +SCOPED(PQGParams); SCOPED(PRFileDesc); SCOPED(SECAlgorithmID); SCOPED(SECKEYEncryptedPrivateKeyInfo); @@ -82,4 +85,9 @@ SCOPED(CERTDistNames); #undef SCOPED +struct StackSECItem : public SECItem { + StackSECItem() : SECItem({siBuffer, nullptr, 0}) {} + ~StackSECItem() { SECITEM_FreeItem(this, PR_FALSE); } +}; + #endif // nss_scoped_ptrs_h__ diff --git a/security/nss/cpputil/scoped_ptrs_smime.h b/security/nss/cpputil/scoped_ptrs_smime.h new file mode 100644 index 0000000000..fc235f7ebe --- /dev/null +++ b/security/nss/cpputil/scoped_ptrs_smime.h @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef scoped_ptrs_smime_h__ +#define scoped_ptrs_smime_h__ + +#include +#include "smime.h" + +struct ScopedDeleteSmime { + void operator()(NSSCMSMessage* id) { NSS_CMSMessage_Destroy(id); } +}; + +template +struct ScopedMaybeDeleteSmime { + void operator()(T* ptr) { + if (ptr) { + ScopedDeleteSmime del; + del(ptr); + } + } +}; + +#define SCOPED(x) \ + typedef std::unique_ptr > Scoped##x + +SCOPED(NSSCMSMessage); + +#undef SCOPED + +#endif // scoped_ptrs_smime_h__ diff --git a/security/nss/cpputil/scoped_ptrs_ssl.h b/security/nss/cpputil/scoped_ptrs_ssl.h index 7eeae8f8f8..581fe423a9 100644 --- a/security/nss/cpputil/scoped_ptrs_ssl.h +++ b/security/nss/cpputil/scoped_ptrs_ssl.h @@ -14,6 +14,7 @@ struct ScopedDeleteSSL { void operator()(SSLResumptionTokenInfo* token) { SSL_DestroyResumptionTokenInfo(token); } + void operator()(SSLAeadContext* ctx) { SSL_DestroyAead(ctx); } }; template @@ -29,6 +30,7 @@ struct ScopedMaybeDeleteSSL { #define SCOPED(x) typedef std::unique_ptr > Scoped##x SCOPED(SSLResumptionTokenInfo); +SCOPED(SSLAeadContext); #undef SCOPED diff --git a/security/nss/cpputil/scoped_ptrs_util.h b/security/nss/cpputil/scoped_ptrs_util.h index 2dbf34e1d3..dc6e1d7525 100644 --- a/security/nss/cpputil/scoped_ptrs_util.h +++ b/security/nss/cpputil/scoped_ptrs_util.h @@ -33,6 +33,7 @@ struct ScopedMaybeDelete { SCOPED(SECAlgorithmID); SCOPED(SECItem); SCOPED(PK11URI); +SCOPED(PLArenaPool); #undef SCOPED diff --git a/security/nss/cpputil/tls_parser.h b/security/nss/cpputil/tls_parser.h index cd9e28fc35..881c5268ec 100644 --- a/security/nss/cpputil/tls_parser.h +++ b/security/nss/cpputil/tls_parser.h @@ -80,6 +80,32 @@ inline std::ostream& operator<<(std::ostream& os, SSLProtocolVariant v) { return os << ((v == ssl_variant_stream) ? "TLS" : "DTLS"); } +inline std::ostream& operator<<(std::ostream& os, SSLContentType v) { + switch (v) { + case ssl_ct_change_cipher_spec: + return os << "CCS"; + case ssl_ct_alert: + return os << "alert"; + case ssl_ct_handshake: + return os << "handshake"; + case ssl_ct_application_data: + return os << "application data"; + case ssl_ct_ack: + return os << "ack"; + } + return os << "UNKNOWN content type " << static_cast(v); +} + +inline std::ostream& operator<<(std::ostream& os, SSLSecretDirection v) { + switch (v) { + case ssl_secret_read: + return os << "read"; + case ssl_secret_write: + return os << "write"; + } + return os << "UNKNOWN secret direction " << static_cast(v); +} + inline bool IsDtls(uint16_t version) { return (version & 0x8000) == 0x8000; } inline uint16_t NormalizeTlsVersion(uint16_t version) { diff --git a/security/nss/doc/Makefile b/security/nss/doc/Makefile index 444a81a30f..a4d85a69ce 100644 --- a/security/nss/doc/Makefile +++ b/security/nss/doc/Makefile @@ -21,7 +21,7 @@ all: prepare all-man all-html prepare: date-and-version mkdir -p html mkdir -p nroff - + clean: rm -f date.xml version.xml *.tar.bz2 rm -f html/*.proc @@ -45,11 +45,11 @@ version.xml: nroff/%.1 : %.xml $(COMPILE.1) $< - + MANPAGES = \ nroff/certutil.1 nroff/cmsutil.1 nroff/crlutil.1 nroff/pk12util.1 \ nroff/modutil.1 nroff/ssltap.1 nroff/derdump.1 nroff/signtool.1 nroff/signver.1 \ -nroff/pp.1 nroff/vfychain.1 nroff/vfyserv.1 +nroff/pp.1 nroff/vfychain.1 nroff/vfyserv.1 nroff/nss-policy-check.1 all-man: prepare $(MANPAGES) @@ -64,6 +64,6 @@ html/%.html : %.xml HTMLPAGES = \ html/certutil.html html/cmsutil.html html/crlutil.html html/pk12util.html html/modutil.html \ html/ssltap.html html/derdump.html html/signtool.html html/signver.html html/pp.html \ -html/vfychain.html html/vfyserv.html +html/vfychain.html html/vfyserv.html html/nss-policy-check.html all-html: prepare $(HTMLPAGES) diff --git a/security/nss/doc/certutil.xml b/security/nss/doc/certutil.xml index 5c3b3501ab..41659e2060 100644 --- a/security/nss/doc/certutil.xml +++ b/security/nss/doc/certutil.xml @@ -179,6 +179,10 @@ Use the -a argument to specify ASCII output. For certificate requests, ASCII output defaults to standard output unless redirected. + + --simple-self-signed + When printing the certificate chain, don't search for a chain if issuer name equals to subject name. + -b validity-time Specify a time at which a certificate is required to be valid. Use when checking certificate validity with the option. The format of the validity-time argument is YYMMDDHHMMSS[+HHMM|-HHMM|Z], which allows offsets to be set relative to the validity end time. Specifying seconds (SS) is optional. When specifying an explicit time, use a Z at the end of the term, YYMMDDHHMMSSZ, to close it. When specifying an offset time, use YYMMDDHHMMSS+HHMM or YYMMDDHHMMSS-HHMM for adding or subtracting time, respectively. diff --git a/security/nss/doc/nss-policy-check.xml b/security/nss/doc/nss-policy-check.xml new file mode 100644 index 0000000000..1d891b8c3f --- /dev/null +++ b/security/nss/doc/nss-policy-check.xml @@ -0,0 +1,97 @@ + + + +]> + + + + + &date; + NSS Security Tools + nss-tools + &version; + + + + NSS-POLICY-CHECK + 1 + + + + nss-policy-check + nss-policy-check policy-file + + + + + nss-policy-check + + + + + Description + nss-policy-check verifies crypto-policy configuration that controls certain crypto algorithms are allowed/disallowed to use in the NSS library. + + The crypto-policy configuration can be stored in either a system-wide configuration file, specified with the POLICY_PATH and POLICY_FILE build options, or in the pkcs11.txt in NSS database. + + + + Usage and Examples + To check the global crypto-policy configuration in /etc/crypto-policies/back-ends/nss.config: + + $ nss-policy-check /etc/crypto-policies/back-ends/nss.config +NSS-POLICY-INFO: LOADED-SUCCESSFULLY +NSS-POLICY-INFO: PRIME256V1 is enabled for KX +NSS-POLICY-INFO: PRIME256V1 is enabled for CERT-SIGNATURE +NSS-POLICY-INFO: SECP256R1 is enabled for KX +NSS-POLICY-INFO: SECP256R1 is enabled for CERT-SIGNATURE +NSS-POLICY-INFO: SECP384R1 is enabled for KX +NSS-POLICY-INFO: SECP384R1 is enabled for CERT-SIGNATURE +... +NSS-POLICY-INFO: NUMBER-OF-SSL-ALG-KX: 13 +NSS-POLICY-INFO: NUMBER-OF-SSL-ALG: 9 +NSS-POLICY-INFO: NUMBER-OF-CERT-SIG: 9 +... +NSS-POLICY-INFO: ciphersuite TLS_AES_128_GCM_SHA256 is enabled +NSS-POLICY-INFO: ciphersuite TLS_CHACHA20_POLY1305_SHA256 is enabled +NSS-POLICY-INFO: ciphersuite TLS_AES_256_GCM_SHA384 is enabled +... +NSS-POLICY-INFO: NUMBER-OF-CIPHERSUITES: 24 +NSS-POLICY-INFO: NUMBER-OF-TLS-VERSIONS: 3 +NSS-POLICY-INFO: NUMBER-OF-DTLS-VERSIONS: 2 + + If there is a failure or warning, it will be prefixed with + NSS-POLICY-FAIL or NSS-POLICY_WARN. + + nss-policy-check exits with 2 if any + failure is found, 1 if any warning is found, or 0 if no errors are + found. + + + + + Additional Resources + For information about NSS and other tools related to NSS (like JSS), check out the NSS project wiki at http://www.mozilla.org/projects/security/pki/nss/. The NSS site relates directly to NSS code changes and releases. + Mailing lists: https://lists.mozilla.org/listinfo/dev-tech-crypto + IRC: Freenode at #dogtag-pki + + + + + Authors + The NSS tools were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google. + + Authors: Elio Maldonado <emaldona@redhat.com>, Deon Lackey <dlackey@redhat.com>. + + + + + + LICENSE + Licensed under 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/. + + + + diff --git a/security/nss/doc/pk12util.xml b/security/nss/doc/pk12util.xml index 3f8eecf1b5..1bd218d147 100644 --- a/security/nss/doc/pk12util.xml +++ b/security/nss/doc/pk12util.xml @@ -108,7 +108,7 @@ - -n | --cert-key-len certKeyLength + --cert-key-len certKeyLength Specify the desired length of the symmetric key to be used to encrypt the certificates and other meta-data. diff --git a/security/nss/gtests/certdb_gtest/cert_unittest.cc b/security/nss/gtests/certdb_gtest/cert_unittest.cc new file mode 100644 index 0000000000..93003fa59c --- /dev/null +++ b/security/nss/gtests/certdb_gtest/cert_unittest.cc @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "gtest/gtest.h" + +#include "nss.h" +#include "secerr.h" +#include "pk11pub.h" +#include "nss_scoped_ptrs.h" + +namespace nss_test { + +class CertTest : public ::testing::Test {}; + +// Tests CERT_GetCertificateDer for the certs we have. +TEST_F(CertTest, GetCertDer) { + // Listing all the certs should get us the default trust anchors. + ScopedCERTCertList certs(PK11_ListCerts(PK11CertListAll, nullptr)); + ASSERT_FALSE(PR_CLIST_IS_EMPTY(&certs->list)); + + for (PRCList* cursor = PR_NEXT_LINK(&certs->list); cursor != &certs->list; + cursor = PR_NEXT_LINK(cursor)) { + CERTCertListNode* node = (CERTCertListNode*)cursor; + SECItem der; + ASSERT_EQ(SECSuccess, CERT_GetCertificateDer(node->cert, &der)); + ASSERT_EQ(0, SECITEM_CompareItem(&der, &node->cert->derCert)); + } +} + +TEST_F(CertTest, GetCertDerBad) { + EXPECT_EQ(SECFailure, CERT_GetCertificateDer(nullptr, nullptr)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + ScopedCERTCertList certs(PK11_ListCerts(PK11CertListAll, nullptr)); + ASSERT_FALSE(PR_CLIST_IS_EMPTY(&certs->list)); + CERTCertListNode* node = (CERTCertListNode*)PR_NEXT_LINK(&certs->list); + EXPECT_EQ(SECFailure, CERT_GetCertificateDer(node->cert, nullptr)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + SECItem der; + EXPECT_EQ(SECFailure, CERT_GetCertificateDer(nullptr, &der)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); +} +} diff --git a/security/nss/gtests/certdb_gtest/certdb_gtest.gyp b/security/nss/gtests/certdb_gtest/certdb_gtest.gyp index 898102defe..7f5bb324b5 100644 --- a/security/nss/gtests/certdb_gtest/certdb_gtest.gyp +++ b/security/nss/gtests/certdb_gtest/certdb_gtest.gyp @@ -12,6 +12,8 @@ 'type': 'executable', 'sources': [ 'alg1485_unittest.cc', + 'cert_unittest.cc', + 'decode_certs_unittest.cc', '<(DEPTH)/gtests/common/gtests.cc' ], 'dependencies': [ @@ -20,6 +22,7 @@ '<(DEPTH)/lib/util/util.gyp:nssutil3', '<(DEPTH)/lib/ssl/ssl.gyp:ssl3', '<(DEPTH)/lib/nss/nss.gyp:nss3', + '<(DEPTH)/lib/smime/smime.gyp:smime3', ] } ], diff --git a/security/nss/gtests/certdb_gtest/decode_certs_unittest.cc b/security/nss/gtests/certdb_gtest/decode_certs_unittest.cc new file mode 100644 index 0000000000..405194edcc --- /dev/null +++ b/security/nss/gtests/certdb_gtest/decode_certs_unittest.cc @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "gtest/gtest.h" + +#include "cert.h" +#include "prerror.h" +#include "secerr.h" + +class DecodeCertsTest : public ::testing::Test {}; + +TEST_F(DecodeCertsTest, EmptyCertPackage) { + // This represents a PKCS#7 ContentInfo with a contentType of + // '2.16.840.1.113730.2.5' (Netscape data-type cert-sequence) and a content + // consisting of an empty SEQUENCE. This is valid ASN.1, but it contains no + // certificates, so CERT_DecodeCertFromPackage should just return a null + // pointer. + unsigned char emptyCertPackage[] = {0x30, 0x0f, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x86, 0xf8, 0x42, 0x02, + 0x05, 0xa0, 0x02, 0x30, 0x00}; + EXPECT_EQ(nullptr, CERT_DecodeCertFromPackage( + reinterpret_cast(emptyCertPackage), + sizeof(emptyCertPackage))); + EXPECT_EQ(SEC_ERROR_BAD_DER, PR_GetError()); +} diff --git a/security/nss/gtests/certdb_gtest/manifest.mn b/security/nss/gtests/certdb_gtest/manifest.mn index 4a3a1fda09..c95cf991f3 100644 --- a/security/nss/gtests/certdb_gtest/manifest.mn +++ b/security/nss/gtests/certdb_gtest/manifest.mn @@ -8,6 +8,8 @@ MODULE = nss CPPSRCS = \ alg1485_unittest.cc \ + cert_unittest.cc \ + decode_certs_unittest.cc \ $(NULL) INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \ diff --git a/security/nss/gtests/common/gtests.cc b/security/nss/gtests/common/gtests.cc index bd5a97a8ed..7e585791b8 100644 --- a/security/nss/gtests/common/gtests.cc +++ b/security/nss/gtests/common/gtests.cc @@ -10,7 +10,23 @@ int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); - if (NSS_NoDB_Init(nullptr) != SECSuccess) { + const char *workdir = ""; + uint32_t flags = NSS_INIT_READONLY; + + for (int i = 0; i < argc; i++) { + if (!strcmp(argv[i], "-d")) { + if (i + 1 >= argc) { + PR_fprintf(PR_STDERR, "Usage: %s [-d [-w]]\n", argv[0]); + exit(2); + } + workdir = argv[i + 1]; + i++; + } else if (!strcmp(argv[i], "-w")) { + flags &= ~NSS_INIT_READONLY; + } + } + + if (NSS_Initialize(workdir, "", "", SECMOD_DB, flags) != SECSuccess) { return 1; } if (NSS_SetDomesticPolicy() != SECSuccess) { diff --git a/security/nss/gtests/manifest.mn b/security/nss/gtests/manifest.mn index 18adb3d7db..24d4ce14fb 100644 --- a/security/nss/gtests/manifest.mn +++ b/security/nss/gtests/manifest.mn @@ -24,6 +24,7 @@ NSS_SRCDIRS = \ cryptohi_gtest \ der_gtest \ pk11_gtest \ + smime_gtest \ softoken_gtest \ ssl_gtest \ $(SYSINIT_GTEST) \ diff --git a/security/nss/gtests/pk11_gtest/manifest.mn b/security/nss/gtests/pk11_gtest/manifest.mn index ea7b43a2b0..75ddb71c31 100644 --- a/security/nss/gtests/pk11_gtest/manifest.mn +++ b/security/nss/gtests/pk11_gtest/manifest.mn @@ -13,6 +13,7 @@ CPPSRCS = \ pk11_ecdsa_unittest.cc \ pk11_encrypt_derive_unittest.cc \ pk11_export_unittest.cc \ + pk11_import_unittest.cc \ pk11_pbkdf2_unittest.cc \ pk11_prf_unittest.cc \ pk11_prng_unittest.cc \ @@ -33,4 +34,3 @@ EXTRA_LIBS = $(DIST)/lib/$(LIB_PREFIX)gtest.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)cpputil.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)gtestutil.$(LIB_SUFFIX) \ $(NULL) - diff --git a/security/nss/gtests/pk11_gtest/pk11_gtest.gyp b/security/nss/gtests/pk11_gtest/pk11_gtest.gyp index c73139b05a..c8d04f017a 100644 --- a/security/nss/gtests/pk11_gtest/pk11_gtest.gyp +++ b/security/nss/gtests/pk11_gtest/pk11_gtest.gyp @@ -18,6 +18,7 @@ 'pk11_curve25519_unittest.cc', 'pk11_ecdsa_unittest.cc', 'pk11_encrypt_derive_unittest.cc', + 'pk11_import_unittest.cc', 'pk11_pbkdf2_unittest.cc', 'pk11_prf_unittest.cc', 'pk11_prng_unittest.cc', diff --git a/security/nss/gtests/smime_gtest/Makefile b/security/nss/gtests/smime_gtest/Makefile new file mode 100644 index 0000000000..0d547e0803 --- /dev/null +++ b/security/nss/gtests/smime_gtest/Makefile @@ -0,0 +1,43 @@ +#! gmake +# +# 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/. + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include ../common/gtest.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### diff --git a/security/nss/gtests/smime_gtest/manifest.mn b/security/nss/gtests/smime_gtest/manifest.mn new file mode 100644 index 0000000000..d3e982ccae --- /dev/null +++ b/security/nss/gtests/smime_gtest/manifest.mn @@ -0,0 +1,22 @@ +# +# 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/. +CORE_DEPTH = ../.. +DEPTH = ../.. +MODULE = nss + +CPPSRCS = \ + smime_unittest.cc \ + $(NULL) + +INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \ + -I$(CORE_DEPTH)/gtests/common \ + -I$(CORE_DEPTH)/cpputil + +REQUIRES = nspr gtest + +PROGRAM = smime_gtest + +EXTRA_LIBS = $(DIST)/lib/$(LIB_PREFIX)gtest.$(LIB_SUFFIX) $(EXTRA_OBJS) \ + $(DIST)/lib/$(LIB_PREFIX)gtestutil.$(LIB_SUFFIX) diff --git a/security/nss/gtests/smime_gtest/smime_gtest.gyp b/security/nss/gtests/smime_gtest/smime_gtest.gyp new file mode 100644 index 0000000000..0ff2804f82 --- /dev/null +++ b/security/nss/gtests/smime_gtest/smime_gtest.gyp @@ -0,0 +1,30 @@ +# 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/. +{ + 'includes': [ + '../../coreconf/config.gypi', + '../common/gtest.gypi', + ], + 'targets': [ + { + 'target_name': 'smime_gtest', + 'type': 'executable', + 'sources': [ + 'smime_unittest.cc', + '<(DEPTH)/gtests/common/gtests.cc' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports', + '<(DEPTH)/gtests/google_test/google_test.gyp:gtest', + '<(DEPTH)/lib/util/util.gyp:nssutil3', + '<(DEPTH)/lib/nss/nss.gyp:nss3', + '<(DEPTH)/lib/smime/smime.gyp:smime', + '<(DEPTH)/lib/ssl/ssl.gyp:ssl3', + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/gtests/smime_gtest/smime_unittest.cc b/security/nss/gtests/smime_gtest/smime_unittest.cc new file mode 100644 index 0000000000..385e19a97e --- /dev/null +++ b/security/nss/gtests/smime_gtest/smime_unittest.cc @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include + +#include "gtest/gtest.h" + +#include "scoped_ptrs_smime.h" +#include "smime.h" + +namespace nss_test { + +// See bug 1507174; this is a CMS serialization (RFC 5652) that claims to be +// 12336 bytes long, which ensures CMS validates the streaming decoder's +// incorrect length. +static const unsigned char kHugeLenAsn1[] = { + 0x30, 0x82, 0x30, 0x30, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x07, 0x02, 0xA0, 0x82, 0x02, 0x30, 0x30, 0x30, 0x02, + 0x01, 0x30, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x0B, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05}; + +// secp256r1 signature with no certs and no attrs +static unsigned char kValidSignature[] = { + 0x30, 0x81, 0xFE, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x07, 0x02, 0xA0, 0x81, 0xF0, 0x30, 0x81, 0xED, 0x02, 0x01, 0x01, 0x31, + 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x07, 0x01, 0x31, 0x81, 0xC9, 0x30, 0x81, 0xC6, 0x02, + 0x01, 0x01, 0x30, 0x5D, 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x53, 0x6F, 0x6D, 0x65, 0x2D, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x18, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, + 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, + 0x4C, 0x74, 0x64, 0x02, 0x14, 0x6B, 0x22, 0xCA, 0x91, 0xE0, 0x71, 0x97, + 0xEB, 0x45, 0x0D, 0x68, 0xC0, 0xD4, 0xB6, 0xE9, 0x45, 0x38, 0x4C, 0xDD, + 0xA3, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x01, 0x05, 0x00, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, + 0x3D, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x48, 0xEB, + 0xE6, 0xBA, 0xFC, 0xFD, 0x83, 0xB3, 0xA2, 0xB5, 0x59, 0x35, 0x0C, 0xA1, + 0x31, 0x0E, 0x2F, 0xE3, 0x8D, 0x81, 0xD8, 0xF5, 0x33, 0xE4, 0x83, 0x87, + 0xB1, 0xFD, 0x43, 0x9D, 0x95, 0x7D, 0x02, 0x21, 0x00, 0xD0, 0x05, 0x0E, + 0x05, 0xA6, 0x80, 0x3C, 0x1A, 0xFE, 0x51, 0xFC, 0x4D, 0x1A, 0x25, 0x05, + 0x78, 0xB5, 0x42, 0xF5, 0xDE, 0x4E, 0x8A, 0xF8, 0xE3, 0xD8, 0x52, 0xDC, + 0x2B, 0x73, 0x80, 0x4A, 0x1A}; + +// See bug 1507135; this is a CMS signature that contains only the OID +static unsigned char kTruncatedSignature[] = {0x30, 0x0B, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x07, 0x02}; + +// secp256r1 signature that's truncated by one byte. +static unsigned char kSlightlyTruncatedSignature[] = { + 0x30, 0x81, 0xFE, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x07, 0x02, 0xA0, 0x81, 0xF0, 0x30, 0x81, 0xED, 0x02, 0x01, 0x01, 0x31, + 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x07, 0x01, 0x31, 0x81, 0xC9, 0x30, 0x81, 0xC6, 0x02, + 0x01, 0x01, 0x30, 0x5D, 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x53, 0x6F, 0x6D, 0x65, 0x2D, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x0C, 0x18, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, + 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, + 0x4C, 0x74, 0x64, 0x02, 0x14, 0x6B, 0x22, 0xCA, 0x91, 0xE0, 0x71, 0x97, + 0xEB, 0x45, 0x0D, 0x68, 0xC0, 0xD4, 0xB6, 0xE9, 0x45, 0x38, 0x4C, 0xDD, + 0xA3, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x01, 0x05, 0x00, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, + 0x3D, 0x04, 0x03, 0x02, 0x04, 0x47, 0x30, 0x45, 0x02, 0x20, 0x48, 0xEB, + 0xE6, 0xBA, 0xFC, 0xFD, 0x83, 0xB3, 0xA2, 0xB5, 0x59, 0x35, 0x0C, 0xA1, + 0x31, 0x0E, 0x2F, 0xE3, 0x8D, 0x81, 0xD8, 0xF5, 0x33, 0xE4, 0x83, 0x87, + 0xB1, 0xFD, 0x43, 0x9D, 0x95, 0x7D, 0x02, 0x21, 0x00, 0xD0, 0x05, 0x0E, + 0x05, 0xA6, 0x80, 0x3C, 0x1A, 0xFE, 0x51, 0xFC, 0x4D, 0x1A, 0x25, 0x05, + 0x78, 0xB5, 0x42, 0xF5, 0xDE, 0x4E, 0x8A, 0xF8, 0xE3, 0xD8, 0x52, 0xDC, + 0x2B, 0x73, 0x80, 0x4A}; + +class SMimeTest : public ::testing::Test {}; + +TEST_F(SMimeTest, InvalidDER) { + PK11SymKey* bulk_key = nullptr; + NSSCMSDecoderContext* dcx = + NSS_CMSDecoder_Start(nullptr, nullptr, nullptr, /* content callback */ + nullptr, nullptr, /* password callback */ + nullptr, /* key callback */ + bulk_key); + ASSERT_NE(nullptr, dcx); + EXPECT_EQ(SECSuccess, NSS_CMSDecoder_Update( + dcx, reinterpret_cast(kHugeLenAsn1), + sizeof(kHugeLenAsn1))); + EXPECT_EQ(nullptr, bulk_key); + ASSERT_FALSE(NSS_CMSDecoder_Finish(dcx)); +} + +TEST_F(SMimeTest, IsSignedValid) { + SECItem sig_der_item = {siBuffer, kValidSignature, sizeof(kValidSignature)}; + + ScopedNSSCMSMessage cms_msg(NSS_CMSMessage_CreateFromDER( + &sig_der_item, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); + + ASSERT_TRUE(cms_msg); + + ASSERT_TRUE(NSS_CMSMessage_IsSigned(cms_msg.get())); +} + +TEST_F(SMimeTest, TruncatedCmsSignature) { + SECItem sig_der_item = {siBuffer, kTruncatedSignature, + sizeof(kTruncatedSignature)}; + + ScopedNSSCMSMessage cms_msg(NSS_CMSMessage_CreateFromDER( + &sig_der_item, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); + + ASSERT_TRUE(cms_msg); + + ASSERT_FALSE(NSS_CMSMessage_IsSigned(cms_msg.get())); +} + +TEST_F(SMimeTest, SlightlyTruncatedCmsSignature) { + SECItem sig_der_item = {siBuffer, kSlightlyTruncatedSignature, + sizeof(kSlightlyTruncatedSignature)}; + + ScopedNSSCMSMessage cms_msg(NSS_CMSMessage_CreateFromDER( + &sig_der_item, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); + + ASSERT_FALSE(cms_msg); + + ASSERT_FALSE(NSS_CMSMessage_IsSigned(cms_msg.get())); +} + +TEST_F(SMimeTest, IsSignedNull) { + ASSERT_FALSE(NSS_CMSMessage_IsSigned(nullptr)); +} + +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/libssl_internals.c b/security/nss/gtests/ssl_gtest/libssl_internals.c index e43113de42..2a9803daab 100644 --- a/security/nss/gtests/ssl_gtest/libssl_internals.c +++ b/security/nss/gtests/ssl_gtest/libssl_internals.c @@ -297,38 +297,6 @@ SSLKEAType SSLInt_GetKEAType(SSLNamedGroup group) { return groupDef->keaType; } -SECStatus SSLInt_SetCipherSpecChangeFunc(PRFileDesc *fd, - sslCipherSpecChangedFunc func, - void *arg) { - sslSocket *ss; - - ss = ssl_FindSocket(fd); - if (!ss) { - return SECFailure; - } - - ss->ssl3.changedCipherSpecFunc = func; - ss->ssl3.changedCipherSpecArg = arg; - - return SECSuccess; -} - -PK11SymKey *SSLInt_CipherSpecToKey(const ssl3CipherSpec *spec) { - return spec->keyMaterial.key; -} - -SSLCipherAlgorithm SSLInt_CipherSpecToAlgorithm(const ssl3CipherSpec *spec) { - return spec->cipherDef->calg; -} - -const PRUint8 *SSLInt_CipherSpecToIv(const ssl3CipherSpec *spec) { - return spec->keyMaterial.iv; -} - -PRUint16 SSLInt_CipherSpecToEpoch(const ssl3CipherSpec *spec) { - return spec->epoch; -} - void SSLInt_SetTicketLifetime(uint32_t lifetime) { ssl_ticket_lifetime = lifetime; } @@ -360,16 +328,14 @@ void SSLInt_RolloverAntiReplay(void) { tls13_AntiReplayRollover(ssl_TimeUsec()); } -SECStatus SSLInt_GetEpochs(PRFileDesc *fd, PRUint16 *readEpoch, - PRUint16 *writeEpoch) { +SECStatus SSLInt_HasPendingHandshakeData(PRFileDesc *fd, PRBool *pending) { sslSocket *ss = ssl_FindSocket(fd); - if (!ss || !readEpoch || !writeEpoch) { + if (!ss) { return SECFailure; } - ssl_GetSpecReadLock(ss); - *readEpoch = ss->ssl3.crSpec->epoch; - *writeEpoch = ss->ssl3.cwSpec->epoch; - ssl_ReleaseSpecReadLock(ss); + ssl_GetSSL3HandshakeLock(ss); + *pending = ss->ssl3.hs.msg_body.len > 0; + ssl_ReleaseSSL3HandshakeLock(ss); return SECSuccess; } diff --git a/security/nss/gtests/ssl_gtest/libssl_internals.h b/security/nss/gtests/ssl_gtest/libssl_internals.h index 3efb362c27..8c78de28f5 100644 --- a/security/nss/gtests/ssl_gtest/libssl_internals.h +++ b/security/nss/gtests/ssl_gtest/libssl_internals.h @@ -39,16 +39,7 @@ SECStatus SSLInt_AdvanceWriteSeqNum(PRFileDesc *fd, PRUint64 to); SECStatus SSLInt_AdvanceReadSeqNum(PRFileDesc *fd, PRUint64 to); SECStatus SSLInt_AdvanceWriteSeqByAWindow(PRFileDesc *fd, PRInt32 extra); SSLKEAType SSLInt_GetKEAType(SSLNamedGroup group); -SECStatus SSLInt_GetEpochs(PRFileDesc *fd, PRUint16 *readEpoch, - PRUint16 *writeEpoch); - -SECStatus SSLInt_SetCipherSpecChangeFunc(PRFileDesc *fd, - sslCipherSpecChangedFunc func, - void *arg); -PRUint16 SSLInt_CipherSpecToEpoch(const ssl3CipherSpec *spec); -PK11SymKey *SSLInt_CipherSpecToKey(const ssl3CipherSpec *spec); -SSLCipherAlgorithm SSLInt_CipherSpecToAlgorithm(const ssl3CipherSpec *spec); -const PRUint8 *SSLInt_CipherSpecToIv(const ssl3CipherSpec *spec); +SECStatus SSLInt_HasPendingHandshakeData(PRFileDesc *fd, PRBool *pending); void SSLInt_SetTicketLifetime(uint32_t lifetime); SECStatus SSLInt_SetSocketMaxEarlyDataSize(PRFileDesc *fd, uint32_t size); void SSLInt_RolloverAntiReplay(void); diff --git a/security/nss/gtests/ssl_gtest/manifest.mn b/security/nss/gtests/ssl_gtest/manifest.mn index 7f4ee79539..13883712ef 100644 --- a/security/nss/gtests/ssl_gtest/manifest.mn +++ b/security/nss/gtests/ssl_gtest/manifest.mn @@ -35,7 +35,9 @@ CPPSRCS = \ ssl_keyupdate_unittest.cc \ ssl_loopback_unittest.cc \ ssl_misc_unittest.cc \ + ssl_primitive_unittest.cc \ ssl_record_unittest.cc \ + ssl_recordsep_unittest.cc \ ssl_recordsize_unittest.cc \ ssl_resumption_unittest.cc \ ssl_renegotiation_unittest.cc \ diff --git a/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc index 3a52ac20c5..8db23e74e1 100644 --- a/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc @@ -176,6 +176,321 @@ TEST_P(TlsConnectGeneric, ClientAuth) { CheckKeys(); } +class TlsCertificateRequestContextRecorder : public TlsHandshakeFilter { + public: + TlsCertificateRequestContextRecorder(const std::shared_ptr& a, + uint8_t handshake_type) + : TlsHandshakeFilter(a, {handshake_type}), buffer_(), filtered_(false) { + EnableDecryption(); + } + + bool filtered() const { return filtered_; } + const DataBuffer& buffer() const { return buffer_; } + + protected: + virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, + const DataBuffer& input, + DataBuffer* output) { + assert(1 < input.len()); + size_t len = input.data()[0]; + assert(len + 1 < input.len()); + buffer_.Assign(input.data() + 1, len); + filtered_ = true; + return KEEP; + } + + private: + DataBuffer buffer_; + bool filtered_; +}; + +// All stream only tests; DTLS isn't supported yet. + +TEST_F(TlsConnectStreamTls13, PostHandshakeAuth) { + EnsureTlsSetup(); + auto capture_cert_req = MakeTlsFilter( + server_, kTlsHandshakeCertificateRequest); + auto capture_certificate = + MakeTlsFilter( + client_, kTlsHandshakeCertificate); + client_->SetupClientAuth(); + EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), + SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); + size_t called = 0; + server_->SetAuthCertificateCallback( + [&called](TlsAgent*, PRBool, PRBool) -> SECStatus { + called++; + return SECSuccess; + }); + Connect(); + EXPECT_EQ(0U, called); + EXPECT_FALSE(capture_cert_req->filtered()); + EXPECT_FALSE(capture_certificate->filtered()); + // Send CertificateRequest. + EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) + << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); + // Need to do a round-trip so that the post-handshake message is + // handled on both client and server. + server_->SendData(50); + client_->ReadBytes(50); + client_->SendData(50); + server_->ReadBytes(50); + EXPECT_EQ(1U, called); + EXPECT_TRUE(capture_cert_req->filtered()); + EXPECT_TRUE(capture_certificate->filtered()); + // Check if a non-empty request context is generated and it is + // properly sent back. + EXPECT_LT(0U, capture_cert_req->buffer().len()); + EXPECT_EQ(capture_cert_req->buffer().len(), + capture_certificate->buffer().len()); + EXPECT_EQ(0, memcmp(capture_cert_req->buffer().data(), + capture_certificate->buffer().data(), + capture_cert_req->buffer().len())); + ScopedCERTCertificate cert1(SSL_PeerCertificate(server_->ssl_fd())); + ScopedCERTCertificate cert2(SSL_LocalCertificate(client_->ssl_fd())); + EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert)); +} + +static SECStatus GetClientAuthDataHook(void* self, PRFileDesc* fd, + CERTDistNames* caNames, + CERTCertificate** clientCert, + SECKEYPrivateKey** clientKey) { + ScopedCERTCertificate cert; + ScopedSECKEYPrivateKey priv; + // use a different certificate than TlsAgent::kClient + if (!TlsAgent::LoadCertificate(TlsAgent::kRsa2048, &cert, &priv)) { + return SECFailure; + } + + *clientCert = cert.release(); + *clientKey = priv.release(); + return SECSuccess; +} + +TEST_F(TlsConnectStreamTls13, PostHandshakeAuthMultiple) { + client_->SetupClientAuth(); + EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), + SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); + size_t called = 0; + server_->SetAuthCertificateCallback( + [&called](TlsAgent*, PRBool, PRBool) -> SECStatus { + called++; + return SECSuccess; + }); + Connect(); + EXPECT_EQ(0U, called); + EXPECT_EQ(nullptr, SSL_PeerCertificate(server_->ssl_fd())); + // Send 1st CertificateRequest. + EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) + << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); + server_->SendData(50); + client_->ReadBytes(50); + client_->SendData(50); + server_->ReadBytes(50); + EXPECT_EQ(1U, called); + ScopedCERTCertificate cert1(SSL_PeerCertificate(server_->ssl_fd())); + ScopedCERTCertificate cert2(SSL_LocalCertificate(client_->ssl_fd())); + EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert)); + // Send 2nd CertificateRequest. + EXPECT_EQ(SECSuccess, SSL_GetClientAuthDataHook( + client_->ssl_fd(), GetClientAuthDataHook, nullptr)); + EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) + << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); + server_->SendData(50); + client_->ReadBytes(50); + client_->SendData(50); + server_->ReadBytes(50); + EXPECT_EQ(2U, called); + ScopedCERTCertificate cert3(SSL_PeerCertificate(server_->ssl_fd())); + ScopedCERTCertificate cert4(SSL_LocalCertificate(client_->ssl_fd())); + EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert3->derCert, &cert4->derCert)); + EXPECT_FALSE(SECITEM_ItemsAreEqual(&cert3->derCert, &cert1->derCert)); +} + +TEST_F(TlsConnectStreamTls13, PostHandshakeAuthConcurrent) { + client_->SetupClientAuth(); + EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), + SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); + Connect(); + // Send 1st CertificateRequest. + EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) + << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); + // Send 2nd CertificateRequest. + EXPECT_EQ(SECFailure, SSL_SendCertificateRequest(server_->ssl_fd())); + EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); +} + +TEST_F(TlsConnectStreamTls13, PostHandshakeAuthMissingExtension) { + client_->SetupClientAuth(); + Connect(); + // Send CertificateRequest, should fail due to missing + // post_handshake_auth extension. + EXPECT_EQ(SECFailure, SSL_SendCertificateRequest(server_->ssl_fd())); + EXPECT_EQ(SSL_ERROR_MISSING_POST_HANDSHAKE_AUTH_EXTENSION, PORT_GetError()); +} + +TEST_F(TlsConnectStreamTls13, PostHandshakeAuthAfterClientAuth) { + client_->SetupClientAuth(); + server_->RequestClientAuth(true); + EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), + SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); + size_t called = 0; + server_->SetAuthCertificateCallback( + [&called](TlsAgent*, PRBool, PRBool) -> SECStatus { + called++; + return SECSuccess; + }); + Connect(); + EXPECT_EQ(1U, called); + ScopedCERTCertificate cert1(SSL_PeerCertificate(server_->ssl_fd())); + ScopedCERTCertificate cert2(SSL_LocalCertificate(client_->ssl_fd())); + EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert)); + // Send CertificateRequest. + EXPECT_EQ(SECSuccess, SSL_GetClientAuthDataHook( + client_->ssl_fd(), GetClientAuthDataHook, nullptr)); + EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) + << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); + server_->SendData(50); + client_->ReadBytes(50); + client_->SendData(50); + server_->ReadBytes(50); + EXPECT_EQ(2U, called); + ScopedCERTCertificate cert3(SSL_PeerCertificate(server_->ssl_fd())); + ScopedCERTCertificate cert4(SSL_LocalCertificate(client_->ssl_fd())); + EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert3->derCert, &cert4->derCert)); + EXPECT_FALSE(SECITEM_ItemsAreEqual(&cert3->derCert, &cert1->derCert)); +} + +// Damages the request context in a CertificateRequest message. +// We don't modify a Certificate message instead, so that the client +// can compute CertificateVerify correctly. +class TlsDamageCertificateRequestContextFilter : public TlsHandshakeFilter { + public: + TlsDamageCertificateRequestContextFilter(const std::shared_ptr& a) + : TlsHandshakeFilter(a, {kTlsHandshakeCertificateRequest}) { + EnableDecryption(); + } + + protected: + virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, + const DataBuffer& input, + DataBuffer* output) { + *output = input; + assert(1 < output->len()); + // The request context has a 1 octet length. + output->data()[1] ^= 73; + return CHANGE; + } +}; + +TEST_F(TlsConnectStreamTls13, PostHandshakeAuthContextMismatch) { + EnsureTlsSetup(); + MakeTlsFilter(server_); + client_->SetupClientAuth(); + EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), + SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); + Connect(); + // Send CertificateRequest. + EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) + << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); + server_->SendData(50); + client_->ReadBytes(50); + client_->SendData(50); + server_->ExpectSendAlert(kTlsAlertIllegalParameter); + server_->ReadBytes(50); + EXPECT_EQ(SSL_ERROR_RX_MALFORMED_CERTIFICATE, PORT_GetError()); + server_->ExpectReadWriteError(); + server_->SendData(50); + client_->ExpectReceiveAlert(kTlsAlertIllegalParameter); + client_->ReadBytes(50); + EXPECT_EQ(SSL_ERROR_ILLEGAL_PARAMETER_ALERT, PORT_GetError()); +} + +// Replaces signature in a CertificateVerify message. +class TlsDamageSignatureFilter : public TlsHandshakeFilter { + public: + TlsDamageSignatureFilter(const std::shared_ptr& a) + : TlsHandshakeFilter(a, {kTlsHandshakeCertificateVerify}) { + EnableDecryption(); + } + + protected: + virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, + const DataBuffer& input, + DataBuffer* output) { + *output = input; + assert(2 < output->len()); + // The signature follows a 2-octet signature scheme. + output->data()[2] ^= 73; + return CHANGE; + } +}; + +TEST_F(TlsConnectStreamTls13, PostHandshakeAuthBadSignature) { + EnsureTlsSetup(); + MakeTlsFilter(client_); + client_->SetupClientAuth(); + EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), + SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); + Connect(); + // Send CertificateRequest. + EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) + << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); + server_->SendData(50); + client_->ReadBytes(50); + client_->SendData(50); + server_->ExpectSendAlert(kTlsAlertDecodeError); + server_->ReadBytes(50); + EXPECT_EQ(SSL_ERROR_RX_MALFORMED_CERT_VERIFY, PORT_GetError()); +} + +TEST_F(TlsConnectStreamTls13, PostHandshakeAuthDecline) { + EnsureTlsSetup(); + auto capture_cert_req = MakeTlsFilter( + server_, kTlsHandshakeCertificateRequest); + auto capture_certificate = + MakeTlsFilter( + client_, kTlsHandshakeCertificate); + client_->SetupClientAuth(); + EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(), + SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE)); + // Client to decline the certificate request. + EXPECT_EQ(SECSuccess, + SSL_GetClientAuthDataHook( + client_->ssl_fd(), + [](void*, PRFileDesc*, CERTDistNames*, CERTCertificate**, + SECKEYPrivateKey**) -> SECStatus { return SECFailure; }, + nullptr)); + size_t called = 0; + server_->SetAuthCertificateCallback( + [&called](TlsAgent*, PRBool, PRBool) -> SECStatus { + called++; + return SECSuccess; + }); + Connect(); + EXPECT_EQ(0U, called); + // Send CertificateRequest. + EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd())) + << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); + server_->SendData(50); + client_->ReadBytes(50); + client_->SendData(50); + server_->ReadBytes(50); + // AuthCertificateCallback is not called, because the client sends + // an empty certificate_list. + EXPECT_EQ(0U, called); + EXPECT_TRUE(capture_cert_req->filtered()); + EXPECT_TRUE(capture_certificate->filtered()); + // Check if a non-empty request context is generated and it is + // properly sent back. + EXPECT_LT(0U, capture_cert_req->buffer().len()); + EXPECT_EQ(capture_cert_req->buffer().len(), + capture_certificate->buffer().len()); + EXPECT_EQ(0, memcmp(capture_cert_req->buffer().data(), + capture_certificate->buffer().data(), + capture_cert_req->buffer().len())); +} + // In TLS 1.3, the client sends its cert rejection on the // second flight, and since it has already received the // server's Finished, it transitions to complete and @@ -273,9 +588,7 @@ class TlsReplaceSignatureSchemeFilter : public TlsHandshakeFilter { TlsReplaceSignatureSchemeFilter(const std::shared_ptr& a, SSLSignatureScheme scheme) : TlsHandshakeFilter(a, {kTlsHandshakeCertificateVerify}), - scheme_(scheme) { - EnableDecryption(); - } + scheme_(scheme) {} protected: virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, @@ -552,7 +865,9 @@ TEST_P(TlsConnectTls12, SignatureAlgorithmDrop) { TEST_P(TlsConnectTls13, UnsupportedSignatureSchemeAlert) { EnsureTlsSetup(); - MakeTlsFilter(server_, ssl_sig_none); + auto filter = + MakeTlsFilter(server_, ssl_sig_none); + filter->EnableDecryption(); ConnectExpectAlert(client_, kTlsAlertIllegalParameter); server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); @@ -563,8 +878,9 @@ TEST_P(TlsConnectTls13, InconsistentSignatureSchemeAlert) { EnsureTlsSetup(); // This won't work because we use an RSA cert by default. - MakeTlsFilter( + auto filter = MakeTlsFilter( server_, ssl_sig_ecdsa_secp256r1_sha256); + filter->EnableDecryption(); ConnectExpectAlert(client_, kTlsAlertIllegalParameter); server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); diff --git a/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc index 0723c9bee5..9cbe9566f1 100644 --- a/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc @@ -62,7 +62,6 @@ TEST_P(TlsConnectGenericPre13, DamageServerSignature) { EnsureTlsSetup(); auto filter = MakeTlsFilter( server_, kTlsHandshakeServerKeyExchange); - filter->EnableDecryption(); ExpectAlert(client_, kTlsAlertDecryptError); ConnectExpectFail(); client_->CheckErrorCode(SEC_ERROR_BAD_SIGNATURE); @@ -84,7 +83,9 @@ TEST_P(TlsConnectGeneric, DamageClientSignature) { server_->RequestClientAuth(true); auto filter = MakeTlsFilter( client_, kTlsHandshakeCertificateVerify); - filter->EnableDecryption(); + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + filter->EnableDecryption(); + } server_->ExpectSendAlert(kTlsAlertDecryptError); // Do these handshakes by hand to avoid race condition on // the client processing the server's alert. diff --git a/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc index f25efc77ad..b441b5c10d 100644 --- a/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc @@ -66,6 +66,38 @@ TEST_P(TlsConnectDatagramPre13, DropServerSecondFlightThrice) { Connect(); } +static void CheckAcks(const std::shared_ptr& acks, + size_t index, std::vector expected) { + ASSERT_LT(index, acks->count()); + const DataBuffer& buf = acks->record(index).buffer; + size_t offset = 2; + uint64_t len; + + EXPECT_EQ(2 + expected.size() * 8, buf.len()); + ASSERT_TRUE(buf.Read(0, 2, &len)); + ASSERT_EQ(static_cast(len + 2), buf.len()); + if ((2 + expected.size() * 8) != buf.len()) { + while (offset < buf.len()) { + uint64_t ack; + ASSERT_TRUE(buf.Read(offset, 8, &ack)); + offset += 8; + std::cerr << "Ack=0x" << std::hex << ack << std::dec << std::endl; + } + return; + } + + for (size_t i = 0; i < expected.size(); ++i) { + uint64_t a = expected[i]; + uint64_t ack; + ASSERT_TRUE(buf.Read(offset, 8, &ack)); + offset += 8; + if (a != ack) { + ADD_FAILURE() << "Wrong ack " << i << " expected=0x" << std::hex << a + << " got=0x" << ack << std::dec; + } + } +} + class TlsDropDatagram13 : public TlsConnectDatagram13, public ::testing::WithParamInterface { public: @@ -139,37 +171,6 @@ class TlsDropDatagram13 : public TlsConnectDatagram13, std::shared_ptr chain_; }; - void CheckAcks(const DropAckChain& chain, size_t index, - std::vector acks) { - const DataBuffer& buf = chain.ack_->record(index).buffer; - size_t offset = 2; - uint64_t len; - - EXPECT_EQ(2 + acks.size() * 8, buf.len()); - ASSERT_TRUE(buf.Read(0, 2, &len)); - ASSERT_EQ(static_cast(len + 2), buf.len()); - if ((2 + acks.size() * 8) != buf.len()) { - while (offset < buf.len()) { - uint64_t ack; - ASSERT_TRUE(buf.Read(offset, 8, &ack)); - offset += 8; - std::cerr << "Ack=0x" << std::hex << ack << std::dec << std::endl; - } - return; - } - - for (size_t i = 0; i < acks.size(); ++i) { - uint64_t a = acks[i]; - uint64_t ack; - ASSERT_TRUE(buf.Read(offset, 8, &ack)); - offset += 8; - if (a != ack) { - ADD_FAILURE() << "Wrong ack " << i << " expected=0x" << std::hex << a - << " got=0x" << ack << std::dec; - } - } - } - void CheckedHandshakeSendReceive() { Handshake(); CheckPostHandshake(); @@ -199,7 +200,7 @@ TEST_P(TlsDropDatagram13, DropClientFirstFlightOnce) { client_->Handshake(); server_->Handshake(); CheckedHandshakeSendReceive(); - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL}); } TEST_P(TlsDropDatagram13, DropServerFirstFlightOnce) { @@ -210,7 +211,7 @@ TEST_P(TlsDropDatagram13, DropServerFirstFlightOnce) { server_->Handshake(); server_filters_.drop_->Disable(); CheckedHandshakeSendReceive(); - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL}); } // Dropping the server's first record also does not produce @@ -223,7 +224,7 @@ TEST_P(TlsDropDatagram13, DropServerFirstRecordOnce) { server_->Handshake(); Handshake(); CheckedHandshakeSendReceive(); - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL}); } // Dropping the second packet of the server's flight should @@ -236,8 +237,8 @@ TEST_P(TlsDropDatagram13, DropServerSecondRecordOnce) { HandshakeAndAck(client_); expected_client_acks_ = 1; CheckedHandshakeSendReceive(); - CheckAcks(client_filters_, 0, {0}); // ServerHello - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + CheckAcks(client_filters_.ack_, 0, {0}); // ServerHello + CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL}); } // Drop the server ACK and verify that the client retransmits @@ -265,8 +266,8 @@ TEST_P(TlsDropDatagram13, DropServerAckOnce) { EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); CheckPostHandshake(); // There should be two copies of the finished ACK - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); - CheckAcks(server_filters_, 1, {0x0002000000000000ULL}); + CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL}); + CheckAcks(server_filters_.ack_, 1, {0x0002000000000000ULL}); } // Drop the client certificate verify. @@ -281,10 +282,10 @@ TEST_P(TlsDropDatagram13, DropClientCertVerify) { expected_server_acks_ = 2; CheckedHandshakeSendReceive(); // Ack of the Cert. - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL}); // Ack of the whole client handshake. CheckAcks( - server_filters_, 1, + server_filters_.ack_, 1, {0x0002000000000000ULL, // CH (we drop everything after this on client) 0x0002000000000003ULL, // CT (2) 0x0002000000000004ULL}); // FIN (2) @@ -310,11 +311,11 @@ TEST_P(TlsDropDatagram13, DropFirstHalfOfServerCertificate) { // as the previous CT1). EXPECT_EQ(ct1_size, server_filters_.record(0).buffer.len()); CheckedHandshakeSendReceive(); - CheckAcks(client_filters_, 0, + CheckAcks(client_filters_.ack_, 0, {0, // SH 0x0002000000000000ULL, // EE 0x0002000000000002ULL}); // CT2 - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL}); } // Shrink the MTU down so that certs get split and drop the second piece. @@ -336,13 +337,13 @@ TEST_P(TlsDropDatagram13, DropSecondHalfOfServerCertificate) { // Check that the first record is CT1 EXPECT_EQ(ct1_size, server_filters_.record(0).buffer.len()); CheckedHandshakeSendReceive(); - CheckAcks(client_filters_, 0, + CheckAcks(client_filters_.ack_, 0, { 0, // SH 0x0002000000000000ULL, // EE 0x0002000000000001ULL, // CT1 }); - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL}); } // In this test, the Certificate message is sent four times, we drop all or part @@ -392,18 +393,18 @@ class TlsFragmentationAndRecoveryTest : public TlsDropDatagram13 { 0, // SH 0x0002000000000000ULL // EE }; - CheckAcks(client_filters_, 0, client_acks); + CheckAcks(client_filters_.ack_, 0, client_acks); // And from the second attempt for the half was kept (we delayed this ACK). client_acks.push_back(0x0002000000000000ULL + second_flight_count + ~dropped_half % 2); - CheckAcks(client_filters_, 1, client_acks); + CheckAcks(client_filters_.ack_, 1, client_acks); // And the third attempt where the first and last thirds got through. client_acks.push_back(0x0002000000000000ULL + second_flight_count + third_flight_count - 1); client_acks.push_back(0x0002000000000000ULL + second_flight_count + third_flight_count + 1); - CheckAcks(client_filters_, 2, client_acks); - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + CheckAcks(client_filters_.ack_, 2, client_acks); + CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL}); } private: @@ -548,7 +549,7 @@ TEST_P(TlsDropDatagram13, NoDropsDuringZeroRtt) { CheckConnected(); SendReceive(); EXPECT_EQ(0U, client_filters_.ack_->count()); - CheckAcks(server_filters_, 0, + CheckAcks(server_filters_.ack_, 0, {0x0001000000000001ULL, // EOED 0x0002000000000000ULL}); // Finished } @@ -567,8 +568,8 @@ TEST_P(TlsDropDatagram13, DropEEDuringZeroRtt) { ExpectEarlyDataAccepted(true); CheckConnected(); SendReceive(); - CheckAcks(client_filters_, 0, {0}); - CheckAcks(server_filters_, 0, + CheckAcks(client_filters_.ack_, 0, {0}); + CheckAcks(server_filters_.ack_, 0, {0x0001000000000002ULL, // EOED 0x0002000000000000ULL}); // Finished } @@ -608,22 +609,22 @@ TEST_P(TlsDropDatagram13, ReorderServerEE) { expected_client_acks_ = 1; HandshakeAndAck(client_); CheckedHandshakeSendReceive(); - CheckAcks(client_filters_, 0, + CheckAcks(client_filters_.ack_, 0, { 0, // SH 0x0002000000000000, // EE }); - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL}); } // The client sends an out of order non-handshake message // but with the handshake key. class TlsSendCipherSpecCapturer { public: - TlsSendCipherSpecCapturer(std::shared_ptr& agent) - : send_cipher_specs_() { - SSLInt_SetCipherSpecChangeFunc(agent->ssl_fd(), CipherSpecChanged, - (void*)this); + TlsSendCipherSpecCapturer(const std::shared_ptr& agent) + : agent_(agent), send_cipher_specs_() { + EXPECT_EQ(SECSuccess, + SSL_SecretCallback(agent_->ssl_fd(), SecretCallback, this)); } std::shared_ptr spec(size_t i) { @@ -634,28 +635,42 @@ class TlsSendCipherSpecCapturer { } private: - static void CipherSpecChanged(void* arg, PRBool sending, - ssl3CipherSpec* newSpec) { - if (!sending) { + static void SecretCallback(PRFileDesc* fd, PRUint16 epoch, + SSLSecretDirection dir, PK11SymKey* secret, + void* arg) { + auto self = static_cast(arg); + std::cerr << self->agent_->role_str() << ": capture " << dir + << " secret for epoch " << epoch << std::endl; + + if (dir == ssl_secret_read) { return; } - auto self = static_cast(arg); + SSLPreliminaryChannelInfo preinfo; + EXPECT_EQ(SECSuccess, + SSL_GetPreliminaryChannelInfo(self->agent_->ssl_fd(), &preinfo, + sizeof(preinfo))); + EXPECT_EQ(sizeof(preinfo), preinfo.length); + EXPECT_TRUE(preinfo.valuesSet & ssl_preinfo_cipher_suite); - auto spec = std::make_shared(); - bool ret = spec->Init(SSLInt_CipherSpecToEpoch(newSpec), - SSLInt_CipherSpecToAlgorithm(newSpec), - SSLInt_CipherSpecToKey(newSpec), - SSLInt_CipherSpecToIv(newSpec)); - EXPECT_EQ(true, ret); + SSLCipherSuiteInfo cipherinfo; + EXPECT_EQ(SECSuccess, + SSL_GetCipherSuiteInfo(preinfo.cipherSuite, &cipherinfo, + sizeof(cipherinfo))); + EXPECT_EQ(sizeof(cipherinfo), cipherinfo.length); + + auto spec = std::make_shared(true, epoch); + EXPECT_TRUE(spec->SetKeys(&cipherinfo, secret)); self->send_cipher_specs_.push_back(spec); } + std::shared_ptr agent_; std::vector> send_cipher_specs_; }; -TEST_P(TlsDropDatagram13, SendOutOfOrderAppWithHandshakeKey) { +TEST_F(TlsConnectDatagram13, SendOutOfOrderAppWithHandshakeKey) { StartConnect(); + // Capturing secrets means that we can't use decrypting filters on the client. TlsSendCipherSpecCapturer capturer(client_); client_->Handshake(); server_->Handshake(); @@ -680,9 +695,12 @@ TEST_P(TlsDropDatagram13, SendOutOfOrderAppWithHandshakeKey) { EXPECT_EQ(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE, PORT_GetError()); } -TEST_P(TlsDropDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) { +TEST_F(TlsConnectDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) { StartConnect(); TlsSendCipherSpecCapturer capturer(client_); + auto acks = MakeTlsFilter(server_, ssl_ct_ack); + acks->EnableDecryption(); + client_->Handshake(); server_->Handshake(); client_->Handshake(); @@ -699,10 +717,10 @@ TEST_P(TlsDropDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) { ssl_ct_handshake, DataBuffer(buf, sizeof(buf)))); server_->Handshake(); - EXPECT_EQ(2UL, server_filters_.ack_->count()); + EXPECT_EQ(2UL, acks->count()); // The server acknowledges client Finished twice. - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); - CheckAcks(server_filters_, 1, {0x0002000000000000ULL}); + CheckAcks(acks, 0, {0x0002000000000000ULL}); + CheckAcks(acks, 1, {0x0002000000000000ULL}); } // Shrink the MTU down so that certs get split and then swap the first and @@ -726,7 +744,7 @@ TEST_P(TlsReorderDatagram13, ReorderServerCertificate) { ShiftDtlsTimers(); CheckedHandshakeSendReceive(); EXPECT_EQ(2UL, server_filters_.records_->count()); // ACK + Data - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + CheckAcks(server_filters_.ack_, 0, {0x0002000000000000ULL}); } TEST_P(TlsReorderDatagram13, DataAfterEOEDDuringZeroRtt) { @@ -761,7 +779,8 @@ TEST_P(TlsReorderDatagram13, DataAfterEOEDDuringZeroRtt) { CheckConnected(); EXPECT_EQ(0U, client_filters_.ack_->count()); // Acknowledgements for EOED and Finished. - CheckAcks(server_filters_, 0, {0x0001000000000002ULL, 0x0002000000000000ULL}); + CheckAcks(server_filters_.ack_, 0, + {0x0001000000000002ULL, 0x0002000000000000ULL}); uint8_t buf[8]; rv = PR_Read(server_->ssl_fd(), buf, sizeof(buf)); EXPECT_EQ(-1, rv); @@ -800,7 +819,8 @@ TEST_P(TlsReorderDatagram13, DataAfterFinDuringZeroRtt) { CheckConnected(); EXPECT_EQ(0U, client_filters_.ack_->count()); // Acknowledgements for EOED and Finished. - CheckAcks(server_filters_, 0, {0x0001000000000002ULL, 0x0002000000000000ULL}); + CheckAcks(server_filters_.ack_, 0, + {0x0001000000000002ULL, 0x0002000000000000ULL}); uint8_t buf[8]; rv = PR_Read(server_->ssl_fd(), buf, sizeof(buf)); EXPECT_EQ(-1, rv); diff --git a/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc index 5819af7468..b3b1eab444 100644 --- a/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc @@ -482,6 +482,73 @@ TEST_P(TlsExtensionTestGeneric, SupportedCurvesTrailingData) { client_, ssl_elliptic_curves_xtn, extension)); } +TEST_P(TlsExtensionTest12, SupportedCurvesDisableX25519) { + // Disable session resumption. + ConfigureSessionCache(RESUME_NONE, RESUME_NONE); + + // Ensure that we can enable its use in the key exchange. + SECStatus rv = + NSS_SetAlgorithmPolicy(SEC_OID_CURVE25519, NSS_USE_ALG_IN_SSL_KX, 0); + ASSERT_EQ(SECSuccess, rv); + rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL, + 0); + ASSERT_EQ(SECSuccess, rv); + + auto capture1 = + MakeTlsFilter(client_, ssl_elliptic_curves_xtn); + Connect(); + + EXPECT_TRUE(capture1->captured()); + const DataBuffer& ext1 = capture1->extension(); + + uint32_t count; + ASSERT_TRUE(ext1.Read(0, 2, &count)); + + // Whether or not we've seen x25519 offered in this handshake. + bool seen1_x25519 = false; + for (size_t offset = 2; offset <= count; offset++) { + uint32_t val; + ASSERT_TRUE(ext1.Read(offset, 2, &val)); + if (val == ssl_grp_ec_curve25519) { + seen1_x25519 = true; + break; + } + } + ASSERT_TRUE(seen1_x25519); + + // Ensure that we can disable its use in the key exchange. + rv = NSS_SetAlgorithmPolicy(SEC_OID_CURVE25519, 0, NSS_USE_ALG_IN_SSL_KX); + ASSERT_EQ(SECSuccess, rv); + rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL, + 0); + ASSERT_EQ(SECSuccess, rv); + + // Clean up after the last run. + Reset(); + auto capture2 = + MakeTlsFilter(client_, ssl_elliptic_curves_xtn); + Connect(); + + EXPECT_TRUE(capture2->captured()); + const DataBuffer& ext2 = capture2->extension(); + + ASSERT_TRUE(ext2.Read(0, 2, &count)); + + // Whether or not we've seen x25519 offered in this handshake. + bool seen2_x25519 = false; + for (size_t offset = 2; offset <= count; offset++) { + uint32_t val; + ASSERT_TRUE(ext2.Read(offset, 2, &val)); + + if (val == ssl_grp_ec_curve25519) { + seen2_x25519 = true; + break; + } + } + + ASSERT_FALSE(seen2_x25519); +} + TEST_P(TlsExtensionTestPre13, SupportedPointsEmpty) { const uint8_t val[] = {0x00}; DataBuffer extension(val, sizeof(val)); @@ -547,6 +614,56 @@ TEST_P(TlsExtensionTest12, SignatureAlgorithmConfiguration) { } } +// This only works on TLS 1.2, since it relies on DSA. +TEST_P(TlsExtensionTest12, SignatureAlgorithmDisableDSA) { + const std::vector schemes = { + ssl_sig_dsa_sha1, ssl_sig_dsa_sha256, ssl_sig_dsa_sha384, + ssl_sig_dsa_sha512, ssl_sig_rsa_pss_rsae_sha256}; + + // Connect with DSA enabled by policy. + SECStatus rv = NSS_SetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, + NSS_USE_ALG_IN_SSL_KX, 0); + ASSERT_EQ(SECSuccess, rv); + rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL, + 0); + ASSERT_EQ(SECSuccess, rv); + + Reset(TlsAgent::kServerDsa); + auto capture1 = + MakeTlsFilter(client_, ssl_signature_algorithms_xtn); + client_->SetSignatureSchemes(schemes.data(), schemes.size()); + Connect(); + + // Check if all the signature algorithms are advertised. + EXPECT_TRUE(capture1->captured()); + const DataBuffer& ext1 = capture1->extension(); + EXPECT_EQ(2U + 2U * schemes.size(), ext1.len()); + + // Connect with DSA disabled by policy. + rv = NSS_SetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, 0, + NSS_USE_ALG_IN_SSL_KX); + ASSERT_EQ(SECSuccess, rv); + rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL, + 0); + ASSERT_EQ(SECSuccess, rv); + + Reset(TlsAgent::kServerDsa); + auto capture2 = + MakeTlsFilter(client_, ssl_signature_algorithms_xtn); + client_->SetSignatureSchemes(schemes.data(), schemes.size()); + ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); + server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM); + client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); + + // Check if no DSA algorithms are advertised. + EXPECT_TRUE(capture2->captured()); + const DataBuffer& ext2 = capture2->extension(); + EXPECT_EQ(2U + 2U, ext2.len()); + uint32_t v = 0; + EXPECT_TRUE(ext2.Read(2, 2, &v)); + EXPECT_EQ(ssl_sig_rsa_pss_rsae_sha256, v); +} + // Temporary test to verify that we choke on an empty ClientKeyShare. // This test will fail when we implement HelloRetryRequest. TEST_P(TlsExtensionTest13, EmptyClientKeyShare) { @@ -1121,6 +1238,10 @@ INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(ExtensionDatagramOnly, TlsExtensionTestDtls, TlsConnectTestBase::kTlsV11Plus); +INSTANTIATE_TEST_CASE_P(ExtensionTls12, TlsExtensionTest12, + ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, + TlsConnectTestBase::kTlsV12)); + INSTANTIATE_TEST_CASE_P(ExtensionTls12Plus, TlsExtensionTest12Plus, ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV12Plus)); diff --git a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp index be1c4ea325..8dbd9fa347 100644 --- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp +++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp @@ -36,7 +36,9 @@ 'ssl_keyupdate_unittest.cc', 'ssl_loopback_unittest.cc', 'ssl_misc_unittest.cc', + 'ssl_primitive_unittest.cc', 'ssl_record_unittest.cc', + 'ssl_recordsep_unittest.cc', 'ssl_recordsize_unittest.cc', 'ssl_resumption_unittest.cc', 'ssl_renegotiation_unittest.cc', diff --git a/security/nss/gtests/ssl_gtest/ssl_primitive_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_primitive_unittest.cc new file mode 100644 index 0000000000..7966e063d6 --- /dev/null +++ b/security/nss/gtests/ssl_gtest/ssl_primitive_unittest.cc @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include + +#include "keyhi.h" +#include "pk11pub.h" +#include "secerr.h" +#include "ssl.h" +#include "sslerr.h" +#include "sslexp.h" +#include "sslproto.h" + +#include "gtest_utils.h" +#include "nss_scoped_ptrs.h" +#include "scoped_ptrs_ssl.h" +#include "tls_connect.h" + +namespace nss_test { + +// From tls_hkdf_unittest.cc: +extern size_t GetHashLength(SSLHashType ht); + +class AeadTest : public ::testing::Test { + public: + AeadTest() : slot_(PK11_GetInternalSlot()) {} + + void InitSecret(SSLHashType hash_type) { + static const uint8_t kData[64] = {'s', 'e', 'c', 'r', 'e', 't'}; + SECItem key_item = {siBuffer, const_cast(kData), + static_cast(GetHashLength(hash_type))}; + PK11SymKey *s = + PK11_ImportSymKey(slot_.get(), CKM_SSL3_MASTER_KEY_DERIVE, + PK11_OriginUnwrap, CKA_DERIVE, &key_item, NULL); + ASSERT_NE(nullptr, s); + secret_.reset(s); + } + + void SetUp() override { + InitSecret(ssl_hash_sha256); + PORT_SetError(0); + } + + protected: + static void EncryptDecrypt(const ScopedSSLAeadContext &ctx, + const uint8_t *ciphertext, size_t ciphertext_len) { + static const uint8_t kAad[] = {'a', 'a', 'd'}; + static const uint8_t kPlaintext[] = {'t', 'e', 'x', 't'}; + static const size_t kMaxSize = 32; + + ASSERT_GE(kMaxSize, ciphertext_len); + + uint8_t output[kMaxSize]; + unsigned int output_len = 0; + EXPECT_EQ(SECSuccess, SSL_AeadEncrypt(ctx.get(), 0, kAad, sizeof(kAad), + kPlaintext, sizeof(kPlaintext), + output, &output_len, sizeof(output))); + ASSERT_EQ(ciphertext_len, static_cast(output_len)); + EXPECT_EQ(0, memcmp(ciphertext, output, ciphertext_len)); + + memset(output, 0, sizeof(output)); + EXPECT_EQ(SECSuccess, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad), + ciphertext, ciphertext_len, output, + &output_len, sizeof(output))); + ASSERT_EQ(sizeof(kPlaintext), static_cast(output_len)); + EXPECT_EQ(0, memcmp(kPlaintext, output, sizeof(kPlaintext))); + + // Now for some tests of decryption failure. + // Truncate the input. + EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad), + ciphertext, ciphertext_len - 1, + output, &output_len, sizeof(output))); + EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError()); + + // Skip the first byte of the AAD. + EXPECT_EQ( + SECFailure, + SSL_AeadDecrypt(ctx.get(), 0, kAad + 1, sizeof(kAad) - 1, ciphertext, + ciphertext_len, output, &output_len, sizeof(output))); + EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError()); + + uint8_t input[kMaxSize] = {0}; + // Toggle a byte of the input. + memcpy(input, ciphertext, ciphertext_len); + input[0] ^= 9; + EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad), + input, ciphertext_len, output, + &output_len, sizeof(output))); + EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError()); + + // Toggle the last byte (the auth tag). + memcpy(input, ciphertext, ciphertext_len); + input[ciphertext_len - 1] ^= 77; + EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad), + input, ciphertext_len, output, + &output_len, sizeof(output))); + EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError()); + + // Toggle some of the AAD. + memcpy(input, kAad, sizeof(kAad)); + input[1] ^= 23; + EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, input, sizeof(kAad), + ciphertext, ciphertext_len, output, + &output_len, sizeof(output))); + EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError()); + } + + protected: + ScopedPK11SymKey secret_; + + private: + ScopedPK11SlotInfo slot_; +}; + +// These tests all use fixed inputs: a fixed secret, a fixed label, and fixed +// inputs. So they have fixed outputs. +static const char *kLabel = "test "; +static const uint8_t kCiphertextAes128Gcm[] = { + 0x11, 0x14, 0xfc, 0x58, 0x4f, 0x44, 0xff, 0x8c, 0xb6, 0xd8, + 0x20, 0xb3, 0xfb, 0x50, 0xd9, 0x3b, 0xd4, 0xc6, 0xe1, 0x14}; +static const uint8_t kCiphertextAes256Gcm[] = { + 0xf7, 0x27, 0x35, 0x80, 0x88, 0xaf, 0x99, 0x85, 0xf2, 0x83, + 0xca, 0xbb, 0x95, 0x42, 0x09, 0x3f, 0x9c, 0xf3, 0x29, 0xf0}; +static const uint8_t kCiphertextChaCha20Poly1305[] = { + 0x4e, 0x89, 0x2c, 0xfa, 0xfc, 0x8c, 0x40, 0x55, 0x6d, 0x7e, + 0x99, 0xac, 0x8e, 0x54, 0x58, 0xb1, 0x18, 0xd2, 0x66, 0x22}; + +TEST_F(AeadTest, AeadBadVersion) { + SSLAeadContext *ctx = nullptr; + ASSERT_EQ(SECFailure, + SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256, + secret_.get(), kLabel, strlen(kLabel), &ctx)); + EXPECT_EQ(nullptr, ctx); +} + +TEST_F(AeadTest, AeadUnsupportedCipher) { + SSLAeadContext *ctx = nullptr; + ASSERT_EQ(SECFailure, + SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_NULL_MD5, + secret_.get(), kLabel, strlen(kLabel), &ctx)); + EXPECT_EQ(nullptr, ctx); +} + +TEST_F(AeadTest, AeadOlderCipher) { + SSLAeadContext *ctx = nullptr; + ASSERT_EQ( + SECFailure, + SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_AES_128_CBC_SHA, + secret_.get(), kLabel, strlen(kLabel), &ctx)); + EXPECT_EQ(nullptr, ctx); +} + +TEST_F(AeadTest, AeadNoLabel) { + SSLAeadContext *ctx = nullptr; + ASSERT_EQ(SECFailure, + SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256, + secret_.get(), nullptr, 12, &ctx)); + EXPECT_EQ(nullptr, ctx); +} + +TEST_F(AeadTest, AeadLongLabel) { + SSLAeadContext *ctx = nullptr; + ASSERT_EQ(SECFailure, + SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256, + secret_.get(), "", 254, &ctx)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + EXPECT_EQ(nullptr, ctx); +} + +TEST_F(AeadTest, AeadNoPointer) { + SSLAeadContext *ctx = nullptr; + ASSERT_EQ(SECFailure, + SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256, + secret_.get(), kLabel, strlen(kLabel), nullptr)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + EXPECT_EQ(nullptr, ctx); +} + +TEST_F(AeadTest, AeadAes128Gcm) { + SSLAeadContext *ctxInit; + ASSERT_EQ(SECSuccess, + SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256, + secret_.get(), kLabel, strlen(kLabel), &ctxInit)); + ScopedSSLAeadContext ctx(ctxInit); + EXPECT_NE(nullptr, ctx); + + EncryptDecrypt(ctx, kCiphertextAes128Gcm, sizeof(kCiphertextAes128Gcm)); +} + +TEST_F(AeadTest, AeadAes256Gcm) { + SSLAeadContext *ctxInit; + ASSERT_EQ(SECSuccess, + SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_256_GCM_SHA384, + secret_.get(), kLabel, strlen(kLabel), &ctxInit)); + ScopedSSLAeadContext ctx(ctxInit); + EXPECT_NE(nullptr, ctx); + + EncryptDecrypt(ctx, kCiphertextAes256Gcm, sizeof(kCiphertextAes256Gcm)); +} + +TEST_F(AeadTest, AeadChaCha20Poly1305) { + SSLAeadContext *ctxInit; + ASSERT_EQ( + SECSuccess, + SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_CHACHA20_POLY1305_SHA256, + secret_.get(), kLabel, strlen(kLabel), &ctxInit)); + ScopedSSLAeadContext ctx(ctxInit); + EXPECT_NE(nullptr, ctx); + + EncryptDecrypt(ctx, kCiphertextChaCha20Poly1305, + sizeof(kCiphertextChaCha20Poly1305)); +} + +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_recordsep_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_recordsep_unittest.cc new file mode 100644 index 0000000000..8a1dea5bfb --- /dev/null +++ b/security/nss/gtests/ssl_gtest/ssl_recordsep_unittest.cc @@ -0,0 +1,576 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "secerr.h" +#include "ssl.h" +#include "sslerr.h" +#include "sslproto.h" + +extern "C" { +// This is not something that should make you happy. +#include "libssl_internals.h" +} + +#include +#include "gtest_utils.h" +#include "nss_scoped_ptrs.h" +#include "tls_connect.h" +#include "tls_filter.h" +#include "tls_parser.h" + +namespace nss_test { + +class HandshakeSecretTracker { + public: + HandshakeSecretTracker(const std::shared_ptr& agent, + uint16_t first_read_epoch, uint16_t first_write_epoch) + : agent_(agent), + next_read_epoch_(first_read_epoch), + next_write_epoch_(first_write_epoch) { + EXPECT_EQ(SECSuccess, + SSL_SecretCallback(agent_->ssl_fd(), + HandshakeSecretTracker::SecretCb, this)); + } + + void CheckComplete() const { + EXPECT_EQ(0, next_read_epoch_); + EXPECT_EQ(0, next_write_epoch_); + } + + private: + static void SecretCb(PRFileDesc* fd, PRUint16 epoch, SSLSecretDirection dir, + PK11SymKey* secret, void* arg) { + HandshakeSecretTracker* t = reinterpret_cast(arg); + t->SecretUpdated(epoch, dir, secret); + } + + void SecretUpdated(PRUint16 epoch, SSLSecretDirection dir, + PK11SymKey* secret) { + if (g_ssl_gtest_verbose) { + std::cerr << agent_->role_str() << ": secret callback for " << dir + << " epoch " << epoch << std::endl; + } + + EXPECT_TRUE(secret); + uint16_t* p; + if (dir == ssl_secret_read) { + p = &next_read_epoch_; + } else { + ASSERT_EQ(ssl_secret_write, dir); + p = &next_write_epoch_; + } + EXPECT_EQ(*p, epoch); + switch (*p) { + case 1: // 1 == 0-RTT, next should be handshake. + case 2: // 2 == handshake, next should be application data. + (*p)++; + break; + + case 3: // 3 == application data, there should be no more. + // Use 0 as a sentinel value. + *p = 0; + break; + + default: + ADD_FAILURE() << "Unexpected next epoch: " << *p; + } + } + + std::shared_ptr agent_; + uint16_t next_read_epoch_; + uint16_t next_write_epoch_; +}; + +TEST_F(TlsConnectTest, HandshakeSecrets) { + ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); + EnsureTlsSetup(); + + HandshakeSecretTracker c(client_, 2, 2); + HandshakeSecretTracker s(server_, 2, 2); + + Connect(); + SendReceive(); + + c.CheckComplete(); + s.CheckComplete(); +} + +TEST_F(TlsConnectTest, ZeroRttSecrets) { + SetupForZeroRtt(); + + HandshakeSecretTracker c(client_, 2, 1); + HandshakeSecretTracker s(server_, 1, 2); + + client_->Set0RttEnabled(true); + server_->Set0RttEnabled(true); + ExpectResumption(RESUME_TICKET); + ZeroRttSendReceive(true, true); + Handshake(); + ExpectEarlyDataAccepted(true); + CheckConnected(); + SendReceive(); + + c.CheckComplete(); + s.CheckComplete(); +} + +class KeyUpdateTracker { + public: + KeyUpdateTracker(const std::shared_ptr& agent, + bool expect_read_secret) + : agent_(agent), expect_read_secret_(expect_read_secret), called_(false) { + EXPECT_EQ(SECSuccess, SSL_SecretCallback(agent_->ssl_fd(), + KeyUpdateTracker::SecretCb, this)); + } + + void CheckCalled() const { EXPECT_TRUE(called_); } + + private: + static void SecretCb(PRFileDesc* fd, PRUint16 epoch, SSLSecretDirection dir, + PK11SymKey* secret, void* arg) { + KeyUpdateTracker* t = reinterpret_cast(arg); + t->SecretUpdated(epoch, dir, secret); + } + + void SecretUpdated(PRUint16 epoch, SSLSecretDirection dir, + PK11SymKey* secret) { + EXPECT_EQ(4U, epoch); + EXPECT_EQ(expect_read_secret_, dir == ssl_secret_read); + EXPECT_TRUE(secret); + called_ = true; + } + + std::shared_ptr agent_; + bool expect_read_secret_; + bool called_; +}; + +TEST_F(TlsConnectTest, KeyUpdateSecrets) { + ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); + Connect(); + // The update is to the client write secret; the server read secret. + KeyUpdateTracker c(client_, false); + KeyUpdateTracker s(server_, true); + EXPECT_EQ(SECSuccess, SSL_KeyUpdate(client_->ssl_fd(), PR_FALSE)); + SendReceive(50); + SendReceive(60); + CheckEpochs(4, 3); + c.CheckCalled(); + s.CheckCalled(); +} + +// BadPrSocket is an instance of a PR IO layer that crashes the test if it is +// ever used for reading or writing. It does that by failing to overwrite any +// of the DummyIOLayerMethods, which all crash when invoked. +class BadPrSocket : public DummyIOLayerMethods { + public: + BadPrSocket(std::shared_ptr& agent) : DummyIOLayerMethods() { + static PRDescIdentity bad_identity = PR_GetUniqueIdentity("bad NSPR id"); + fd_ = DummyIOLayerMethods::CreateFD(bad_identity, this); + + // This is terrible, but NSPR doesn't provide an easy way to replace the + // bottom layer of an IO stack. Take the DummyPrSocket and replace its + // NSPR method vtable with the ones from this object. + dummy_layer_ = + PR_GetIdentitiesLayer(agent->ssl_fd(), DummyPrSocket::LayerId()); + original_methods_ = dummy_layer_->methods; + original_secret_ = dummy_layer_->secret; + dummy_layer_->methods = fd_->methods; + dummy_layer_->secret = reinterpret_cast(this); + } + + // This will be destroyed before the agent, so we need to restore the state + // before we tampered with it. + virtual ~BadPrSocket() { + dummy_layer_->methods = original_methods_; + dummy_layer_->secret = original_secret_; + } + + private: + ScopedPRFileDesc fd_; + PRFileDesc* dummy_layer_; + const PRIOMethods* original_methods_; + PRFilePrivate* original_secret_; +}; + +class StagedRecords { + public: + StagedRecords(std::shared_ptr& agent) : agent_(agent), records_() { + EXPECT_EQ(SECSuccess, + SSL_RecordLayerWriteCallback( + agent_->ssl_fd(), StagedRecords::StageRecordData, this)); + } + + virtual ~StagedRecords() { + // Uninstall so that the callback doesn't fire during cleanup. + EXPECT_EQ(SECSuccess, + SSL_RecordLayerWriteCallback(agent_->ssl_fd(), nullptr, nullptr)); + } + + bool empty() const { return records_.empty(); } + + void ForwardAll(std::shared_ptr& peer) { + EXPECT_NE(agent_, peer) << "can't forward to self"; + for (auto r : records_) { + r.Forward(peer); + } + records_.clear(); + } + + // This forwards all saved data and checks the resulting state. + void ForwardAll(std::shared_ptr& peer, + TlsAgent::State expected_state) { + ForwardAll(peer); + switch (expected_state) { + case TlsAgent::STATE_CONNECTED: + // The handshake callback should have been called, so check that before + // checking that SSL_ForceHandshake succeeds. + EXPECT_EQ(expected_state, peer->state()); + EXPECT_EQ(SECSuccess, SSL_ForceHandshake(peer->ssl_fd())); + break; + + case TlsAgent::STATE_CONNECTING: + // Check that SSL_ForceHandshake() blocks. + EXPECT_EQ(SECFailure, SSL_ForceHandshake(peer->ssl_fd())); + EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); + // Update and check the state. + peer->Handshake(); + EXPECT_EQ(TlsAgent::STATE_CONNECTING, peer->state()); + break; + + default: + ADD_FAILURE() << "No idea how to handle this state"; + } + } + + void ForwardPartial(std::shared_ptr& peer) { + if (records_.empty()) { + ADD_FAILURE() << "No records to slice"; + return; + } + auto& last = records_.back(); + auto tail = last.SliceTail(); + ForwardAll(peer, TlsAgent::STATE_CONNECTING); + records_.push_back(tail); + EXPECT_EQ(TlsAgent::STATE_CONNECTING, peer->state()); + } + + private: + // A single record. + class StagedRecord { + public: + StagedRecord(const std::string role, uint16_t epoch, SSLContentType ct, + const uint8_t* data, size_t len) + : role_(role), epoch_(epoch), content_type_(ct), data_(data, len) { + if (g_ssl_gtest_verbose) { + std::cerr << role_ << ": staged epoch " << epoch_ << " " + << content_type_ << ": " << data_ << std::endl; + } + } + + // This forwards staged data to the identified agent. + void Forward(std::shared_ptr& peer) { + // Now there should be staged data. + EXPECT_FALSE(data_.empty()); + if (g_ssl_gtest_verbose) { + std::cerr << role_ << ": forward " << data_ << std::endl; + } + EXPECT_EQ(SECSuccess, + SSL_RecordLayerData(peer->ssl_fd(), epoch_, content_type_, + data_.data(), + static_cast(data_.len()))); + } + + // Slices the tail off this record and returns it. + StagedRecord SliceTail() { + size_t slice = 1; + if (data_.len() <= slice) { + ADD_FAILURE() << "record too small to slice in two"; + slice = 0; + } + size_t keep = data_.len() - slice; + StagedRecord tail(role_, epoch_, content_type_, data_.data() + keep, + slice); + data_.Truncate(keep); + return tail; + } + + private: + std::string role_; + uint16_t epoch_; + SSLContentType content_type_; + DataBuffer data_; + }; + + // This is an SSLRecordWriteCallback that stages data. + static SECStatus StageRecordData(PRFileDesc* fd, PRUint16 epoch, + SSLContentType content_type, + const PRUint8* data, unsigned int len, + void* arg) { + auto stage = reinterpret_cast(arg); + stage->records_.push_back(StagedRecord(stage->agent_->role_str(), epoch, + content_type, data, + static_cast(len))); + return SECSuccess; + } + + std::shared_ptr& agent_; + std::deque records_; +}; + +// Attempting to feed application data in before the handshake is complete +// should be caught. +static void RefuseApplicationData(std::shared_ptr& peer, + uint16_t epoch) { + static const uint8_t d[] = {1, 2, 3}; + EXPECT_EQ(SECFailure, + SSL_RecordLayerData(peer->ssl_fd(), epoch, ssl_ct_application_data, + d, static_cast(sizeof(d)))); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); +} + +static void SendForwardReceive(std::shared_ptr& sender, + StagedRecords& sender_stage, + std::shared_ptr& receiver) { + const size_t count = 10; + sender->SendData(count, count); + sender_stage.ForwardAll(receiver); + receiver->ReadBytes(count); +} + +TEST_P(TlsConnectStream, ReplaceRecordLayer) { + StartConnect(); + client_->SetServerKeyBits(server_->server_key_bits()); + + // BadPrSocket installs an IO layer that crashes when the SSL layer attempts + // to read or write. + BadPrSocket bad_layer_client(client_); + BadPrSocket bad_layer_server(server_); + + // StagedRecords installs a handler for unprotected data from the socket, and + // captures that data. + StagedRecords client_stage(client_); + StagedRecords server_stage(server_); + + // Both peers should refuse application data from epoch 0. + RefuseApplicationData(client_, 0); + RefuseApplicationData(server_, 0); + + // This first call forwards nothing, but it causes the client to handshake, + // which starts things off. This stages the ClientHello as a result. + server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING); + // This processes the ClientHello and stages the first server flight. + client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING); + RefuseApplicationData(server_, 1); + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + // Process the server flight and the client is done. + server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED); + client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED); + } else { + server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING); + RefuseApplicationData(client_, 1); + client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED); + server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED); + } + CheckKeys(); + + // Reading and writing application data should work. + SendForwardReceive(client_, client_stage, server_); + SendForwardReceive(server_, server_stage, client_); +} + +static SECStatus AuthCompleteBlock(TlsAgent*, PRBool, PRBool) { + return SECWouldBlock; +} + +TEST_P(TlsConnectStream, ReplaceRecordLayerAsyncLateAuth) { + StartConnect(); + client_->SetServerKeyBits(server_->server_key_bits()); + + BadPrSocket bad_layer_client(client_); + BadPrSocket bad_layer_server(server_); + StagedRecords client_stage(client_); + StagedRecords server_stage(server_); + + client_->SetAuthCertificateCallback(AuthCompleteBlock); + + server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING); + client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING); + server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING); + + // Prior to TLS 1.3, the client sends its second flight immediately. But in + // TLS 1.3, a client won't send a Finished until it is happy with the server + // certificate. So blocking certificate validation causes the client to send + // nothing. + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + ASSERT_TRUE(client_stage.empty()); + + // Client should have stopped reading when it saw the Certificate message, + // so it will be reading handshake epoch, and writing cleartext. + client_->CheckEpochs(2, 0); + // Server should be reading handshake, and writing application data. + server_->CheckEpochs(2, 3); + + // Handshake again and the client will read the remainder of the server's + // flight, but it will remain blocked. + client_->Handshake(); + ASSERT_TRUE(client_stage.empty()); + EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); + } else { + // In prior versions, the client's second flight is always sent. + ASSERT_FALSE(client_stage.empty()); + } + + // Now declare the certificate good. + EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0)); + client_->Handshake(); + ASSERT_FALSE(client_stage.empty()); + + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state()); + client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED); + } else { + client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED); + server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED); + } + CheckKeys(); + + // Reading and writing application data should work. + SendForwardReceive(client_, client_stage, server_); +} + +TEST_F(TlsConnectStreamTls13, ReplaceRecordLayerAsyncPostHandshake) { + StartConnect(); + client_->SetServerKeyBits(server_->server_key_bits()); + + BadPrSocket bad_layer_client(client_); + BadPrSocket bad_layer_server(server_); + StagedRecords client_stage(client_); + StagedRecords server_stage(server_); + + client_->SetAuthCertificateCallback(AuthCompleteBlock); + + server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING); + client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING); + server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING); + + ASSERT_TRUE(client_stage.empty()); + client_->Handshake(); + ASSERT_TRUE(client_stage.empty()); + EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); + + // Now declare the certificate good. + EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0)); + client_->Handshake(); + ASSERT_FALSE(client_stage.empty()); + + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state()); + client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED); + } else { + client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED); + server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED); + } + CheckKeys(); + + // Reading and writing application data should work. + SendForwardReceive(client_, client_stage, server_); + + // Post-handshake messages should work here. + EXPECT_EQ(SECSuccess, SSL_SendSessionTicket(server_->ssl_fd(), nullptr, 0)); + SendForwardReceive(server_, server_stage, client_); +} + +// This test ensures that data is correctly forwarded when the handshake is +// resumed after asynchronous server certificate authentication, when +// SSL_AuthCertificateComplete() is called. The logic for resuming the +// handshake involves a different code path than the usual one, so this test +// exercises that code fully. +TEST_F(TlsConnectStreamTls13, ReplaceRecordLayerAsyncEarlyAuth) { + StartConnect(); + client_->SetServerKeyBits(server_->server_key_bits()); + + BadPrSocket bad_layer_client(client_); + BadPrSocket bad_layer_server(server_); + StagedRecords client_stage(client_); + StagedRecords server_stage(server_); + + client_->SetAuthCertificateCallback(AuthCompleteBlock); + + server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTING); + client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTING); + + // Send a partial flight on to the client. + // This includes enough to trigger the certificate callback. + server_stage.ForwardPartial(client_); + EXPECT_TRUE(client_stage.empty()); + + // Declare the certificate good. + EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0)); + client_->Handshake(); + EXPECT_TRUE(client_stage.empty()); + + // Send the remainder of the server flight. + PRBool pending = PR_FALSE; + EXPECT_EQ(SECSuccess, + SSLInt_HasPendingHandshakeData(client_->ssl_fd(), &pending)); + EXPECT_EQ(PR_TRUE, pending); + EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); + server_stage.ForwardAll(client_, TlsAgent::STATE_CONNECTED); + client_stage.ForwardAll(server_, TlsAgent::STATE_CONNECTED); + CheckKeys(); + + SendForwardReceive(server_, server_stage, client_); +} + +TEST_P(TlsConnectStream, ForwardDataFromWrongEpoch) { + const uint8_t data[] = {1}; + Connect(); + uint16_t next_epoch; + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + EXPECT_EQ(SECFailure, + SSL_RecordLayerData(client_->ssl_fd(), 2, ssl_ct_application_data, + data, sizeof(data))); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()) + << "Passing data from an old epoch is rejected"; + next_epoch = 4; + } else { + // Prior to TLS 1.3, the epoch is only updated once during the handshake. + next_epoch = 2; + } + EXPECT_EQ(SECFailure, + SSL_RecordLayerData(client_->ssl_fd(), next_epoch, + ssl_ct_application_data, data, sizeof(data))); + EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()) + << "Passing data from a future epoch blocks"; +} + +TEST_F(TlsConnectStreamTls13, ForwardInvalidData) { + const uint8_t data[1] = {0}; + + EnsureTlsSetup(); + // Zero-length data. + EXPECT_EQ(SECFailure, SSL_RecordLayerData(client_->ssl_fd(), 0, + ssl_ct_application_data, data, 0)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + // NULL data. + EXPECT_EQ(SECFailure, + SSL_RecordLayerData(client_->ssl_fd(), 0, ssl_ct_application_data, + nullptr, 1)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); +} + +TEST_F(TlsConnectDatagram13, ForwardDataDtls) { + EnsureTlsSetup(); + const uint8_t data[1] = {0}; + EXPECT_EQ(SECFailure, + SSL_RecordLayerData(client_->ssl_fd(), 0, ssl_ct_application_data, + data, sizeof(data))); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); +} + +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc index 0a54ae1a80..5668994204 100644 --- a/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc @@ -123,9 +123,11 @@ TEST_P(TlsConnectGeneric, RecordSizeMaximum) { EnsureTlsSetup(); auto client_max = MakeTlsFilter(client_); - client_max->EnableDecryption(); auto server_max = MakeTlsFilter(server_); - server_max->EnableDecryption(); + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + client_max->EnableDecryption(); + server_max->EnableDecryption(); + } Connect(); client_->SendData(send_size, send_size); @@ -140,7 +142,9 @@ TEST_P(TlsConnectGeneric, RecordSizeMaximum) { TEST_P(TlsConnectGeneric, RecordSizeMinimumClient) { EnsureTlsSetup(); auto server_max = MakeTlsFilter(server_); - server_max->EnableDecryption(); + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + server_max->EnableDecryption(); + } client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64); Connect(); @@ -152,7 +156,9 @@ TEST_P(TlsConnectGeneric, RecordSizeMinimumClient) { TEST_P(TlsConnectGeneric, RecordSizeMinimumServer) { EnsureTlsSetup(); auto client_max = MakeTlsFilter(client_); - client_max->EnableDecryption(); + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + client_max->EnableDecryption(); + } server_->SetOption(SSL_RECORD_SIZE_LIMIT, 64); Connect(); @@ -164,9 +170,11 @@ TEST_P(TlsConnectGeneric, RecordSizeMinimumServer) { TEST_P(TlsConnectGeneric, RecordSizeAsymmetric) { EnsureTlsSetup(); auto client_max = MakeTlsFilter(client_); - client_max->EnableDecryption(); auto server_max = MakeTlsFilter(server_); - server_max->EnableDecryption(); + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + client_max->EnableDecryption(); + server_max->EnableDecryption(); + } client_->SetOption(SSL_RECORD_SIZE_LIMIT, 64); server_->SetOption(SSL_RECORD_SIZE_LIMIT, 100); @@ -256,9 +264,11 @@ class TlsRecordPadder : public TlsRecordFilter { return KEEP; } + uint16_t protection_epoch; uint8_t inner_content_type; DataBuffer plaintext; - if (!Unprotect(header, record, &inner_content_type, &plaintext)) { + if (!Unprotect(header, record, &protection_epoch, &inner_content_type, + &plaintext)) { return KEEP; } @@ -267,8 +277,8 @@ class TlsRecordPadder : public TlsRecordFilter { } DataBuffer ciphertext; - bool ok = - Protect(header, inner_content_type, plaintext, &ciphertext, padding_); + bool ok = Protect(spec(protection_epoch), header, inner_content_type, + plaintext, &ciphertext, padding_); EXPECT_TRUE(ok); if (!ok) { return KEEP; @@ -334,7 +344,9 @@ TEST_P(TlsConnectGeneric, RecordSizeCapExtensionClient) { client_->SetOption(SSL_RECORD_SIZE_LIMIT, 16385); auto capture = MakeTlsFilter(client_, ssl_record_size_limit_xtn); - capture->EnableDecryption(); + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + capture->EnableDecryption(); + } Connect(); uint64_t val = 0; @@ -352,7 +364,9 @@ TEST_P(TlsConnectGeneric, RecordSizeCapExtensionServer) { server_->SetOption(SSL_RECORD_SIZE_LIMIT, 16385); auto capture = MakeTlsFilter(server_, ssl_record_size_limit_xtn); - capture->EnableDecryption(); + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + capture->EnableDecryption(); + } Connect(); uint64_t val = 0; @@ -393,10 +407,24 @@ TEST_P(TlsConnectGeneric, RecordSizeServerExtensionInvalid) { static const uint8_t v[] = {0xf4, 0x1f}; auto replace = MakeTlsFilter( server_, ssl_record_size_limit_xtn, DataBuffer(v, sizeof(v))); - replace->EnableDecryption(); + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + replace->EnableDecryption(); + } ConnectExpectAlert(client_, kTlsAlertIllegalParameter); } +TEST_P(TlsConnectGeneric, RecordSizeServerExtensionExtra) { + EnsureTlsSetup(); + server_->SetOption(SSL_RECORD_SIZE_LIMIT, 1000); + static const uint8_t v[] = {0x01, 0x00, 0x00}; + auto replace = MakeTlsFilter( + server_, ssl_record_size_limit_xtn, DataBuffer(v, sizeof(v))); + if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { + replace->EnableDecryption(); + } + ConnectExpectAlert(client_, kTlsAlertDecodeError); +} + class RecordSizeDefaultsTest : public ::testing::Test { public: void SetUp() { diff --git a/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc index a75dbb7aa7..44e6854140 100644 --- a/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc @@ -214,12 +214,6 @@ class TestPolicyVersionRange ASSERT_EQ(SECSuccess, rv); rv = NSS_OptionSet(NSS_DTLS_VERSION_MAX_POLICY, saved_max_dtls_); ASSERT_EQ(SECSuccess, rv); - // If it wasn't set initially, clear the bit that we set. - if (!(saved_algorithm_policy_ & NSS_USE_POLICY_IN_SSL)) { - rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, 0, - NSS_USE_POLICY_IN_SSL); - ASSERT_EQ(SECSuccess, rv); - } } private: @@ -233,16 +227,12 @@ class TestPolicyVersionRange ASSERT_EQ(SECSuccess, rv); rv = NSS_OptionGet(NSS_DTLS_VERSION_MAX_POLICY, &saved_max_dtls_); ASSERT_EQ(SECSuccess, rv); - rv = NSS_GetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, - &saved_algorithm_policy_); - ASSERT_EQ(SECSuccess, rv); } int32_t saved_min_tls_; int32_t saved_max_tls_; int32_t saved_min_dtls_; int32_t saved_max_dtls_; - uint32_t saved_algorithm_policy_; }; VersionPolicy saved_version_policy_; diff --git a/security/nss/gtests/ssl_gtest/test_io.cc b/security/nss/gtests/ssl_gtest/test_io.cc index 6d792c520c..4a7f914599 100644 --- a/security/nss/gtests/ssl_gtest/test_io.cc +++ b/security/nss/gtests/ssl_gtest/test_io.cc @@ -25,10 +25,13 @@ namespace nss_test { if (g_ssl_gtest_verbose) LOG(a); \ } while (false) +PRDescIdentity DummyPrSocket::LayerId() { + static PRDescIdentity id = PR_GetUniqueIdentity("dummysocket"); + return id; +} + ScopedPRFileDesc DummyPrSocket::CreateFD() { - static PRDescIdentity test_fd_identity = - PR_GetUniqueIdentity("testtransportadapter"); - return DummyIOLayerMethods::CreateFD(test_fd_identity, this); + return DummyIOLayerMethods::CreateFD(DummyPrSocket::LayerId(), this); } void DummyPrSocket::Reset() { @@ -136,19 +139,18 @@ int32_t DummyPrSocket::Write(PRFileDesc *f, const void *buf, int32_t length) { DataBuffer filtered; PacketFilter::Action action = PacketFilter::KEEP; if (filter_) { + LOGV("Original packet: " << packet); action = filter_->Process(packet, &filtered); } switch (action) { case PacketFilter::CHANGE: - LOG("Original packet: " << packet); LOG("Filtered packet: " << filtered); dst->PacketReceived(filtered); break; case PacketFilter::DROP: - LOG("Droppped packet: " << packet); + LOG("Drop packet"); break; case PacketFilter::KEEP: - LOGV("Packet: " << packet); dst->PacketReceived(packet); break; } diff --git a/security/nss/gtests/ssl_gtest/test_io.h b/security/nss/gtests/ssl_gtest/test_io.h index 062ae86c8b..8efd2305b0 100644 --- a/security/nss/gtests/ssl_gtest/test_io.h +++ b/security/nss/gtests/ssl_gtest/test_io.h @@ -68,6 +68,8 @@ class DummyPrSocket : public DummyIOLayerMethods { write_error_(0) {} virtual ~DummyPrSocket() {} + static PRDescIdentity LayerId(); + // Create a file descriptor that will reference this object. The fd must not // live longer than this adapter; call PR_Close() before. ScopedPRFileDesc CreateFD(); diff --git a/security/nss/gtests/ssl_gtest/tls_agent.cc b/security/nss/gtests/ssl_gtest/tls_agent.cc index fb66196b5b..e726c6a61a 100644 --- a/security/nss/gtests/ssl_gtest/tls_agent.cc +++ b/security/nss/gtests/ssl_gtest/tls_agent.cc @@ -640,6 +640,16 @@ void TlsAgent::CheckAlpn(SSLNextProtoState expected_state, } } +void TlsAgent::CheckEpochs(uint16_t expected_read, + uint16_t expected_write) const { + uint16_t read_epoch = 0; + uint16_t write_epoch = 0; + EXPECT_EQ(SECSuccess, + SSL_GetCurrentEpoch(ssl_fd(), &read_epoch, &write_epoch)); + EXPECT_EQ(expected_read, read_epoch) << role_str() << " read epoch"; + EXPECT_EQ(expected_write, write_epoch) << role_str() << " write epoch"; +} + void TlsAgent::EnableSrtp() { EXPECT_TRUE(EnsureTlsSetup()); const uint16_t ciphers[] = {SRTP_AES128_CM_HMAC_SHA1_80, diff --git a/security/nss/gtests/ssl_gtest/tls_agent.h b/security/nss/gtests/ssl_gtest/tls_agent.h index 0202218682..a2ffe7711c 100644 --- a/security/nss/gtests/ssl_gtest/tls_agent.h +++ b/security/nss/gtests/ssl_gtest/tls_agent.h @@ -139,6 +139,7 @@ class TlsAgent : public PollTarget { const std::string& expected = "") const; void EnableSrtp(); void CheckSrtp() const; + void CheckEpochs(uint16_t expected_read, uint16_t expected_write) const; void CheckErrorCode(int32_t expected) const; void WaitForErrorCode(int32_t expected, uint32_t delay) const; // Send data on the socket, encrypting it. diff --git a/security/nss/gtests/ssl_gtest/tls_connect.cc b/security/nss/gtests/ssl_gtest/tls_connect.cc index c48ae38ecf..1d1dfd85df 100644 --- a/security/nss/gtests/ssl_gtest/tls_connect.cc +++ b/security/nss/gtests/ssl_gtest/tls_connect.cc @@ -167,18 +167,8 @@ void TlsConnectTestBase::CheckShares( void TlsConnectTestBase::CheckEpochs(uint16_t client_epoch, uint16_t server_epoch) const { - uint16_t read_epoch = 0; - uint16_t write_epoch = 0; - - EXPECT_EQ(SECSuccess, - SSLInt_GetEpochs(client_->ssl_fd(), &read_epoch, &write_epoch)); - EXPECT_EQ(server_epoch, read_epoch) << "client read epoch"; - EXPECT_EQ(client_epoch, write_epoch) << "client write epoch"; - - EXPECT_EQ(SECSuccess, - SSLInt_GetEpochs(server_->ssl_fd(), &read_epoch, &write_epoch)); - EXPECT_EQ(client_epoch, read_epoch) << "server read epoch"; - EXPECT_EQ(server_epoch, write_epoch) << "server write epoch"; + client_->CheckEpochs(server_epoch, client_epoch); + server_->CheckEpochs(client_epoch, server_epoch); } void TlsConnectTestBase::ClearStats() { @@ -193,12 +183,33 @@ void TlsConnectTestBase::ClearServerCache() { SSL_ConfigServerSessionIDCache(1024, 0, 0, g_working_dir_path.c_str()); } +void TlsConnectTestBase::SaveAlgorithmPolicy() { + saved_policies_.clear(); + for (auto it = algorithms_.begin(); it != algorithms_.end(); ++it) { + uint32_t policy; + SECStatus rv = NSS_GetAlgorithmPolicy(*it, &policy); + ASSERT_EQ(SECSuccess, rv); + saved_policies_.push_back(std::make_tuple(*it, policy)); + } +} + +void TlsConnectTestBase::RestoreAlgorithmPolicy() { + for (auto it = saved_policies_.begin(); it != saved_policies_.end(); ++it) { + auto algorithm = std::get<0>(*it); + auto policy = std::get<1>(*it); + SECStatus rv = NSS_SetAlgorithmPolicy( + algorithm, policy, NSS_USE_POLICY_IN_SSL | NSS_USE_ALG_IN_SSL_KX); + ASSERT_EQ(SECSuccess, rv); + } +} + void TlsConnectTestBase::SetUp() { SSL_ConfigServerSessionIDCache(1024, 0, 0, g_working_dir_path.c_str()); SSLInt_ClearSelfEncryptKey(); SSLInt_SetTicketLifetime(30); SSL_SetupAntiReplay(1 * PR_USEC_PER_SEC, 1, 3); ClearStats(); + SaveAlgorithmPolicy(); Init(); } @@ -209,6 +220,7 @@ void TlsConnectTestBase::TearDown() { SSL_ClearSessionCache(); SSLInt_ClearSelfEncryptKey(); SSL_ShutdownServerSessionIDCache(); + RestoreAlgorithmPolicy(); } void TlsConnectTestBase::Init() { diff --git a/security/nss/gtests/ssl_gtest/tls_connect.h b/security/nss/gtests/ssl_gtest/tls_connect.h index 0004945011..1a61376014 100644 --- a/security/nss/gtests/ssl_gtest/tls_connect.h +++ b/security/nss/gtests/ssl_gtest/tls_connect.h @@ -132,6 +132,9 @@ class TlsConnectTestBase : public ::testing::Test { // Move the DTLS timers for both endpoints to pop the next timer. void ShiftDtlsTimers(); + void SaveAlgorithmPolicy(); + void RestoreAlgorithmPolicy(); + protected: SSLProtocolVariant variant_; std::shared_ptr client_; @@ -149,6 +152,14 @@ class TlsConnectTestBase : public ::testing::Test { // NSS will move this final entry to the front when used with ALPN. const uint8_t alpn_dummy_val_[4] = {0x01, 0x62, 0x01, 0x61}; + // A list of algorithm IDs whose policies need to be preserved + // around test cases. In particular, DSA is checked in + // ssl_extension_unittest.cc. + const std::vector algorithms_ = {SEC_OID_APPLY_SSL_POLICY, + SEC_OID_ANSIX9_DSA_SIGNATURE, + SEC_OID_CURVE25519}; + std::vector> saved_policies_; + private: void CheckResumption(SessionResumptionMode expected); void CheckExtendedMasterSecret(); diff --git a/security/nss/gtests/ssl_gtest/tls_esni_unittest.cc b/security/nss/gtests/ssl_gtest/tls_esni_unittest.cc index 3c860a0b2b..dbac56f13c 100644 --- a/security/nss/gtests/ssl_gtest/tls_esni_unittest.cc +++ b/security/nss/gtests/ssl_gtest/tls_esni_unittest.cc @@ -305,11 +305,14 @@ TEST_P(TlsConnectTls13, ConnectEsniHrr) { server_, kTlsHandshakeHelloRetryRequest); auto filter = MakeTlsFilter(client_, ssl_server_name_xtn); - auto cfilter = - MakeTlsFilter(client_, ssl_server_name_xtn); + auto filter2 = + MakeTlsFilter(client_, ssl_server_name_xtn, true); + client_->SetFilter(std::make_shared( + ChainedPacketFilterInit({filter, filter2}))); server_->SetSniCallback(SniCallback); Connect(); - CheckSniExtension(cfilter->extension()); + CheckSniExtension(filter->extension()); + CheckSniExtension(filter2->extension()); EXPECT_NE(0UL, hrr_capture->buffer().len()); } diff --git a/security/nss/gtests/ssl_gtest/tls_filter.cc b/security/nss/gtests/ssl_gtest/tls_filter.cc index 25ad606fcc..b2917274b4 100644 --- a/security/nss/gtests/ssl_gtest/tls_filter.cc +++ b/security/nss/gtests/ssl_gtest/tls_filter.cc @@ -45,40 +45,65 @@ void TlsVersioned::WriteStream(std::ostream& stream) const { } } -void TlsRecordFilter::EnableDecryption() { - SSLInt_SetCipherSpecChangeFunc(agent()->ssl_fd(), CipherSpecChanged, - (void*)this); +TlsRecordFilter::TlsRecordFilter(const std::shared_ptr& a) + : agent_(a) { + cipher_specs_.emplace_back(a->variant() == ssl_variant_datagram, 0); } -void TlsRecordFilter::CipherSpecChanged(void* arg, PRBool sending, - ssl3CipherSpec* newSpec) { - TlsRecordFilter* self = static_cast(arg); - PRBool isServer = self->agent()->role() == TlsAgent::SERVER; +void TlsRecordFilter::EnableDecryption() { + EXPECT_EQ(SECSuccess, + SSL_SecretCallback(agent()->ssl_fd(), SecretCallback, this)); + decrypting_ = true; +} +void TlsRecordFilter::SecretCallback(PRFileDesc* fd, PRUint16 epoch, + SSLSecretDirection dir, PK11SymKey* secret, + void* arg) { + TlsRecordFilter* self = static_cast(arg); if (g_ssl_gtest_verbose) { - std::cerr << (isServer ? "server" : "client") << ": " - << (sending ? "send" : "receive") - << " cipher spec changed: " << newSpec->epoch << " (" - << newSpec->phase << ")" << std::endl; + std::cerr << self->agent()->role_str() << ": " << dir + << " secret changed for epoch " << epoch << std::endl; } - if (!sending) { + + if (dir == ssl_secret_read) { return; } - uint64_t seq_no; - if (self->agent()->variant() == ssl_variant_datagram) { - seq_no = static_cast(SSLInt_CipherSpecToEpoch(newSpec)) << 48; - } else { - seq_no = 0; + for (auto& spec : self->cipher_specs_) { + ASSERT_NE(spec.epoch(), epoch) << "duplicate spec for epoch " << epoch; } - self->in_sequence_number_ = seq_no; - self->out_sequence_number_ = seq_no; - self->dropped_record_ = false; - self->cipher_spec_.reset(new TlsCipherSpec()); - bool ret = self->cipher_spec_->Init( - SSLInt_CipherSpecToEpoch(newSpec), SSLInt_CipherSpecToAlgorithm(newSpec), - SSLInt_CipherSpecToKey(newSpec), SSLInt_CipherSpecToIv(newSpec)); - EXPECT_EQ(true, ret); + + SSLPreliminaryChannelInfo preinfo; + EXPECT_EQ(SECSuccess, + SSL_GetPreliminaryChannelInfo(self->agent()->ssl_fd(), &preinfo, + sizeof(preinfo))); + EXPECT_EQ(sizeof(preinfo), preinfo.length); + + // Check the version. + if (preinfo.valuesSet & ssl_preinfo_version) { + EXPECT_EQ(SSL_LIBRARY_VERSION_TLS_1_3, preinfo.protocolVersion); + } else { + EXPECT_EQ(1U, epoch); + } + + uint16_t suite; + if (epoch == 1) { + // 0-RTT + EXPECT_TRUE(preinfo.valuesSet & ssl_preinfo_0rtt_cipher_suite); + suite = preinfo.zeroRttCipherSuite; + } else { + EXPECT_TRUE(preinfo.valuesSet & ssl_preinfo_cipher_suite); + suite = preinfo.cipherSuite; + } + + SSLCipherSuiteInfo cipherinfo; + EXPECT_EQ(SECSuccess, + SSL_GetCipherSuiteInfo(suite, &cipherinfo, sizeof(cipherinfo))); + EXPECT_EQ(sizeof(cipherinfo), cipherinfo.length); + + bool is_dtls = self->agent()->variant() == ssl_variant_datagram; + self->cipher_specs_.emplace_back(is_dtls, epoch); + EXPECT_TRUE(self->cipher_specs_.back().SetKeys(&cipherinfo, secret)); } bool TlsRecordFilter::is_dtls13() const { @@ -95,6 +120,23 @@ bool TlsRecordFilter::is_dtls13() const { info.canSendEarlyData; } +// Gets the cipher spec that matches the specified epoch. +TlsCipherSpec& TlsRecordFilter::spec(uint16_t write_epoch) { + for (auto& sp : cipher_specs_) { + if (sp.epoch() == write_epoch) { + return sp; + } + } + + // If we aren't decrypting, provide a cipher spec that does nothing other than + // count sequence numbers. + EXPECT_FALSE(decrypting_) << "No spec available for epoch " << write_epoch; + ; + bool is_dtls = agent()->variant() == ssl_variant_datagram; + cipher_specs_.emplace_back(is_dtls, write_epoch); + return cipher_specs_.back(); +} + PacketFilter::Action TlsRecordFilter::Filter(const DataBuffer& input, DataBuffer* output) { // Disable during shutdown. @@ -108,34 +150,28 @@ PacketFilter::Action TlsRecordFilter::Filter(const DataBuffer& input, output->Allocate(input.len()); TlsParser parser(input); + // This uses the current write spec for the purposes of parsing the epoch and + // sequence number from the header. This might be wrong because we can + // receive records from older specs, but guessing is good enough: + // - In DTLS, parsing the sequence number corrects any errors. + // - In TLS, we don't use the sequence number unless decrypting, where we use + // trial decryption to get the right epoch. + uint16_t write_epoch = 0; + SECStatus rv = SSL_GetCurrentEpoch(agent()->ssl_fd(), nullptr, &write_epoch); + if (rv != SECSuccess) { + ADD_FAILURE() << "unable to read epoch"; + return KEEP; + } + uint64_t guess_seqno = static_cast(write_epoch) << 48; + while (parser.remaining()) { TlsRecordHeader header; DataBuffer record; - - if (!header.Parse(is_dtls13(), in_sequence_number_, &parser, &record)) { + if (!header.Parse(is_dtls13(), guess_seqno, &parser, &record)) { ADD_FAILURE() << "not a valid record"; return KEEP; } - // Track the sequence number, which is necessary for stream mode when - // decrypting and for TLS 1.3 datagram to recover the sequence number. - // - // We reset the counter when the cipher spec changes, but that notification - // appears before a record is sent. If multiple records are sent with - // different cipher specs, this would fail. This filters out cleartext - // records, so we don't get confused by handshake messages that are sent at - // the same time as encrypted records. Sequence numbers are therefore - // likely to be incorrect for cleartext records. - // - // This isn't perfectly robust: if there is a change from an active cipher - // spec to another active cipher spec (KeyUpdate for instance) AND writes - // are consolidated across that change, this code could use the wrong - // sequence numbers when re-encrypting records with the old keys. - if (header.content_type() == ssl_ct_application_data) { - in_sequence_number_ = - (std::max)(in_sequence_number_, header.sequence_number() + 1); - } - if (FilterRecord(header, record, &offset, output) != KEEP) { changed = true; } else { @@ -159,14 +195,16 @@ PacketFilter::Action TlsRecordFilter::FilterRecord( DataBuffer filtered; uint8_t inner_content_type; DataBuffer plaintext; + uint16_t protection_epoch = 0; - if (!Unprotect(header, record, &inner_content_type, &plaintext)) { - if (g_ssl_gtest_verbose) { - std::cerr << "unprotect failed: " << header << ":" << record << std::endl; - } + if (!Unprotect(header, record, &protection_epoch, &inner_content_type, + &plaintext)) { + std::cerr << agent()->role_str() << ": unprotect failed: " << header << ":" + << record << std::endl; return KEEP; } + auto& protection_spec = spec(protection_epoch); TlsRecordHeader real_header(header.variant(), header.version(), inner_content_type, header.sequence_number()); @@ -174,7 +212,9 @@ PacketFilter::Action TlsRecordFilter::FilterRecord( // In stream mode, even if something doesn't change we need to re-encrypt if // previous packets were dropped. if (action == KEEP) { - if (header.is_dtls() || !dropped_record_) { + if (header.is_dtls() || !protection_spec.record_dropped()) { + // Count every outgoing packet. + protection_spec.RecordProtected(); return KEEP; } filtered = plaintext; @@ -182,7 +222,7 @@ PacketFilter::Action TlsRecordFilter::FilterRecord( if (action == DROP) { std::cerr << "record drop: " << header << ":" << record << std::endl; - dropped_record_ = true; + protection_spec.RecordDropped(); return DROP; } @@ -192,19 +232,18 @@ PacketFilter::Action TlsRecordFilter::FilterRecord( std::cerr << "record new: " << filtered << std::endl; } - uint64_t seq_num; - if (header.is_dtls() || !cipher_spec_ || - header.content_type() != ssl_ct_application_data) { - seq_num = header.sequence_number(); - } else { - seq_num = out_sequence_number_++; + uint64_t seq_num = protection_spec.next_out_seqno(); + if (!decrypting_ && header.is_dtls()) { + // Copy over the epoch, which isn't tracked when not decrypting. + seq_num |= header.sequence_number() & (0xffffULL << 48); } + TlsRecordHeader out_header(header.variant(), header.version(), header.content_type(), seq_num); DataBuffer ciphertext; - bool rv = Protect(out_header, inner_content_type, filtered, &ciphertext); - EXPECT_TRUE(rv); + bool rv = Protect(protection_spec, out_header, inner_content_type, filtered, + &ciphertext); if (!rv) { return KEEP; } @@ -227,15 +266,20 @@ uint64_t TlsRecordHeader::RecoverSequenceNumber(uint64_t expected, uint32_t partial, size_t partial_bits) { EXPECT_GE(32U, partial_bits); - uint64_t mask = (1 << partial_bits) - 1; + uint64_t mask = (1ULL << partial_bits) - 1; // First we determine the highest possible value. This is half the - // expressible range above the expected value. - uint64_t cap = expected + (1ULL << (partial_bits - 1)); + // expressible range above the expected value, less 1. + // + // We subtract the extra 1 from the cap so that when given a choice between + // the equidistant expected+N and expected-N we want to chose the lower. With + // 0-RTT, we sometimes have to recover an epoch of 1 when we expect an epoch + // of 3 and with 2 partial bits, the alternative result of 5 is wrong. + uint64_t cap = expected + (1ULL << (partial_bits - 1)) - 1; // Add the partial piece in. e.g., xxxx789a and 1234 becomes xxxx1234. uint64_t seq_no = (cap & ~mask) | partial; // If the partial value is higher than the same partial piece from the cap, // then the real value has to be lower. e.g., xxxx1234 can't become xxxx5678. - if (partial > (cap & mask)) { + if (partial > (cap & mask) && (seq_no >= (1ULL << partial_bits))) { seq_no -= 1ULL << partial_bits; } return seq_no; @@ -375,16 +419,41 @@ size_t TlsRecordHeader::Write(DataBuffer* buffer, size_t offset, bool TlsRecordFilter::Unprotect(const TlsRecordHeader& header, const DataBuffer& ciphertext, + uint16_t* protection_epoch, uint8_t* inner_content_type, DataBuffer* plaintext) { - if (!cipher_spec_ || header.content_type() != ssl_ct_application_data) { + if (!decrypting_ || header.content_type() != ssl_ct_application_data) { + // Maintain the epoch and sequence number for plaintext records. + uint16_t ep = 0; + if (agent()->variant() == ssl_variant_datagram) { + ep = static_cast(header.sequence_number() >> 48); + } + spec(ep).RecordUnprotected(header.sequence_number()); + *protection_epoch = ep; *inner_content_type = header.content_type(); *plaintext = ciphertext; return true; } - if (!cipher_spec_->Unprotect(header, ciphertext, plaintext)) { - return false; + uint16_t ep = 0; + if (agent()->variant() == ssl_variant_datagram) { + ep = static_cast(header.sequence_number() >> 48); + if (!spec(ep).Unprotect(header, ciphertext, plaintext)) { + return false; + } + } else { + // In TLS, records aren't clearly labelled with their epoch, and we + // can't just use the newest keys because the same flight of messages can + // contain multiple epochs. So... trial decrypt! + for (size_t i = cipher_specs_.size() - 1; i > 0; --i) { + if (cipher_specs_[i].Unprotect(header, ciphertext, plaintext)) { + ep = cipher_specs_[i].epoch(); + break; + } + } + if (!ep) { + return false; + } } size_t len = plaintext->len(); @@ -396,33 +465,45 @@ bool TlsRecordFilter::Unprotect(const TlsRecordHeader& header, return false; } + *protection_epoch = ep; *inner_content_type = plaintext->data()[len - 1]; plaintext->Truncate(len - 1); if (g_ssl_gtest_verbose) { - std::cerr << "unprotect: " << std::hex << header.sequence_number() - << std::dec << " type=" << static_cast(*inner_content_type) + std::cerr << agent()->role_str() << ": unprotect: epoch=" << ep + << " seq=" << std::hex << header.sequence_number() << std::dec << " " << *plaintext << std::endl; } return true; } -bool TlsRecordFilter::Protect(const TlsRecordHeader& header, +bool TlsRecordFilter::Protect(TlsCipherSpec& protection_spec, + const TlsRecordHeader& header, uint8_t inner_content_type, const DataBuffer& plaintext, DataBuffer* ciphertext, size_t padding) { - if (!cipher_spec_ || header.content_type() != ssl_ct_application_data) { + if (!protection_spec.is_protected()) { + // Not protected, just keep the sequence numbers updated. + protection_spec.RecordProtected(); *ciphertext = plaintext; return true; } - if (g_ssl_gtest_verbose) { - std::cerr << "protect: " << header.sequence_number() << std::endl; - } + DataBuffer padded; padded.Allocate(plaintext.len() + 1 + padding); size_t offset = padded.Write(0, plaintext.data(), plaintext.len()); padded.Write(offset, inner_content_type, 1); - return cipher_spec_->Protect(header, padded, ciphertext); + + bool ok = protection_spec.Protect(header, padded, ciphertext); + if (!ok) { + ADD_FAILURE() << "protect fail"; + } else if (g_ssl_gtest_verbose) { + std::cerr << agent()->role_str() + << ": protect: epoch=" << protection_spec.epoch() + << " seq=" << std::hex << header.sequence_number() << std::dec + << " " << *ciphertext << std::endl; + } + return ok; } bool IsHelloRetry(const DataBuffer& body) { diff --git a/security/nss/gtests/ssl_gtest/tls_filter.h b/security/nss/gtests/ssl_gtest/tls_filter.h index 2b6e886456..9c75ae960b 100644 --- a/security/nss/gtests/ssl_gtest/tls_filter.h +++ b/security/nss/gtests/ssl_gtest/tls_filter.h @@ -97,13 +97,7 @@ inline std::shared_ptr MakeTlsFilter(const std::shared_ptr& agent, // Abstract filter that operates on entire (D)TLS records. class TlsRecordFilter : public PacketFilter { public: - TlsRecordFilter(const std::shared_ptr& a) - : agent_(a), - count_(0), - cipher_spec_(), - dropped_record_(false), - in_sequence_number_(0), - out_sequence_number_(0) {} + TlsRecordFilter(const std::shared_ptr& a); std::shared_ptr agent() const { return agent_.lock(); } @@ -118,10 +112,11 @@ class TlsRecordFilter : public PacketFilter { // behavior. void EnableDecryption(); bool Unprotect(const TlsRecordHeader& header, const DataBuffer& cipherText, - uint8_t* inner_content_type, DataBuffer* plaintext); - bool Protect(const TlsRecordHeader& header, uint8_t inner_content_type, - const DataBuffer& plaintext, DataBuffer* ciphertext, - size_t padding = 0); + uint16_t* protection_epoch, uint8_t* inner_content_type, + DataBuffer* plaintext); + bool Protect(TlsCipherSpec& protection_spec, const TlsRecordHeader& header, + uint8_t inner_content_type, const DataBuffer& plaintext, + DataBuffer* ciphertext, size_t padding = 0); protected: // There are two filter functions which can be overriden. Both are @@ -146,20 +141,17 @@ class TlsRecordFilter : public PacketFilter { } bool is_dtls13() const; + TlsCipherSpec& spec(uint16_t epoch); private: - static void CipherSpecChanged(void* arg, PRBool sending, - ssl3CipherSpec* newSpec); + static void SecretCallback(PRFileDesc* fd, PRUint16 epoch, + SSLSecretDirection dir, PK11SymKey* secret, + void* arg); std::weak_ptr agent_; - size_t count_; - std::unique_ptr cipher_spec_; - // Whether we dropped a record since the cipher spec changed. - bool dropped_record_; - // The sequence number we use for reading records as they are written. - uint64_t in_sequence_number_; - // The sequence number we use for writing modified records. - uint64_t out_sequence_number_; + size_t count_ = 0; + std::vector cipher_specs_; + bool decrypting_ = false; }; inline std::ostream& operator<<(std::ostream& stream, const TlsVersioned& v) { diff --git a/security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc b/security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc index 004da3b1cc..e1ad9e9f09 100644 --- a/security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc +++ b/security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc @@ -7,6 +7,9 @@ #include #include "nss.h" #include "pk11pub.h" +#include "secerr.h" +#include "sslproto.h" +#include "sslexp.h" #include "tls13hkdf.h" #include "databuffer.h" @@ -56,6 +59,39 @@ const size_t kHashLength[] = { 64, /* ssl_hash_sha512 */ }; +size_t GetHashLength(SSLHashType hash) { + size_t i = static_cast(hash); + if (i < PR_ARRAY_SIZE(kHashLength)) { + return kHashLength[i]; + } + ADD_FAILURE() << "Unknown hash: " << hash; + return 0; +} + +CK_MECHANISM_TYPE GetHkdfMech(SSLHashType hash) { + switch (hash) { + case ssl_hash_sha256: + return CKM_NSS_HKDF_SHA256; + case ssl_hash_sha384: + return CKM_NSS_HKDF_SHA384; + default: + ADD_FAILURE() << "Unknown hash: " << hash; + } + return CKM_INVALID_MECHANISM; +} + +PRUint16 GetSomeCipherSuiteForHash(SSLHashType hash) { + switch (hash) { + case ssl_hash_sha256: + return TLS_AES_128_GCM_SHA256; + case ssl_hash_sha384: + return TLS_AES_256_GCM_SHA384; + default: + ADD_FAILURE() << "Unknown hash: " << hash; + } + return 0; +} + const std::string kHashName[] = {"None", "MD5", "SHA-1", "SHA-224", "SHA-256", "SHA-384", "SHA-512"}; @@ -64,7 +100,7 @@ static void ImportKey(ScopedPK11SymKey* to, const DataBuffer& key, ASSERT_LT(hash_type, sizeof(kHashLength)); ASSERT_LE(kHashLength[hash_type], key.len()); SECItem key_item = {siBuffer, const_cast(key.data()), - static_cast(kHashLength[hash_type])}; + static_cast(GetHashLength(hash_type))}; PK11SymKey* inner = PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, PK11_OriginUnwrap, @@ -112,15 +148,19 @@ class TlsHkdfTest : public ::testing::Test, ImportKey(&k2_, kKey2, hash_type_, slot_.get()); } - void VerifyKey(const ScopedPK11SymKey& key, const DataBuffer& expected) { + void VerifyKey(const ScopedPK11SymKey& key, CK_MECHANISM_TYPE expected_mech, + const DataBuffer& expected_value) { + EXPECT_EQ(expected_mech, PK11_GetMechanism(key.get())); + SECStatus rv = PK11_ExtractKeyValue(key.get()); ASSERT_EQ(SECSuccess, rv); SECItem* key_data = PK11_GetKeyData(key.get()); ASSERT_NE(nullptr, key_data); - EXPECT_EQ(expected.len(), key_data->len); - EXPECT_EQ(0, memcmp(expected.data(), key_data->data, expected.len())); + EXPECT_EQ(expected_value.len(), key_data->len); + EXPECT_EQ( + 0, memcmp(expected_value.data(), key_data->data, expected_value.len())); } void HkdfExtract(const ScopedPK11SymKey& ikmk1, const ScopedPK11SymKey& ikmk2, @@ -133,7 +173,15 @@ class TlsHkdfTest : public ::testing::Test, ScopedPK11SymKey prkk(prk); DumpKey("Output", prkk); - VerifyKey(prkk, expected); + VerifyKey(prkk, GetHkdfMech(base_hash), expected); + + // Now test the public wrapper. + PRUint16 cs = GetSomeCipherSuiteForHash(base_hash); + rv = SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3, cs, ikmk1.get(), + ikmk2.get(), &prk); + ASSERT_EQ(SECSuccess, rv); + ASSERT_NE(nullptr, prk); + VerifyKey(ScopedPK11SymKey(prk), GetHkdfMech(base_hash), expected); } void HkdfExpandLabel(ScopedPK11SymKey* prk, SSLHashType base_hash, @@ -150,6 +198,32 @@ class TlsHkdfTest : public ::testing::Test, ASSERT_EQ(SECSuccess, rv); DumpData("Output", &output[0], output.size()); EXPECT_EQ(0, memcmp(expected.data(), &output[0], expected.len())); + + // Verify that the public API produces the same result. + PRUint16 cs = GetSomeCipherSuiteForHash(base_hash); + PK11SymKey* secret; + rv = SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3, cs, prk->get(), + session_hash, session_hash_len, label, label_len, + &secret); + EXPECT_EQ(SECSuccess, rv); + ASSERT_NE(nullptr, prk); + VerifyKey(ScopedPK11SymKey(secret), GetHkdfMech(base_hash), expected); + + // Verify that a key can be created with a different key type and size. + rv = SSL_HkdfExpandLabelWithMech( + SSL_LIBRARY_VERSION_TLS_1_3, cs, prk->get(), session_hash, + session_hash_len, label, label_len, CKM_DES3_CBC_PAD, 24, &secret); + EXPECT_EQ(SECSuccess, rv); + ASSERT_NE(nullptr, prk); + ScopedPK11SymKey with_mech(secret); + EXPECT_EQ(static_cast(CKM_DES3_CBC_PAD), + PK11_GetMechanism(with_mech.get())); + // Just verify that the key is the right size. + rv = PK11_ExtractKeyValue(with_mech.get()); + ASSERT_EQ(SECSuccess, rv); + SECItem* key_data = PK11_GetKeyData(with_mech.get()); + ASSERT_NE(nullptr, key_data); + EXPECT_EQ(24U, key_data->len); } protected: @@ -175,7 +249,7 @@ TEST_P(TlsHkdfTest, HkdfNullNull) { 0x10, 0xba, 0x18, 0xe2, 0x35, 0x7e, 0x71, 0x69, 0x71, 0xf9, 0x36, 0x2f, 0x2c, 0x2f, 0xe2, 0xa7, 0x6b, 0xfd, 0x78, 0xdf, 0xec, 0x4e, 0xa9, 0xb5}}; - const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]); + const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_)); HkdfExtract(nullptr, nullptr, hash_type_, expected_data); } @@ -193,7 +267,7 @@ TEST_P(TlsHkdfTest, HkdfKey1Only) { 0x57, 0xc2, 0x76, 0x9f, 0x3f, 0x83, 0x45, 0x2f, 0xf6, 0xf3, 0x56, 0x1f, 0x58, 0x63, 0xdb, 0x88, 0xda, 0x40, 0xce, 0x63, 0x7d, 0x24, 0x37, 0xf3}}; - const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]); + const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_)); HkdfExtract(k1_, nullptr, hash_type_, expected_data); } @@ -211,7 +285,7 @@ TEST_P(TlsHkdfTest, HkdfKey2Only) { 0xd4, 0x6a, 0xf6, 0xe5, 0xec, 0xea, 0xf8, 0x7d, 0x91, 0x71, 0x81, 0xf1, 0xdb, 0x3b, 0xaf, 0xbf, 0xde, 0x71, 0x61, 0x15, 0xeb, 0xb5, 0x5f, 0x68}}; - const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]); + const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_)); HkdfExtract(nullptr, k2_, hash_type_, expected_data); } @@ -229,7 +303,7 @@ TEST_P(TlsHkdfTest, HkdfKey1Key2) { 0x1c, 0x5b, 0x98, 0x0b, 0x02, 0x92, 0x3f, 0xfd, 0x73, 0x5a, 0x6f, 0x2a, 0x95, 0xa3, 0xee, 0xf6, 0xd6, 0x8e, 0x6f, 0x86, 0xea, 0x63, 0xf8, 0x33}}; - const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]); + const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_)); HkdfExtract(k1_, k2_, hash_type_, expected_data); } @@ -247,12 +321,122 @@ TEST_P(TlsHkdfTest, HkdfExpandLabel) { 0x74, 0xf7, 0x8b, 0x06, 0x38, 0x28, 0x06, 0x37, 0x75, 0x23, 0xa2, 0xb7, 0x34, 0xb1, 0x72, 0x2e, 0x59, 0x6d, 0x5a, 0x31, 0xf5, 0x53, 0xab, 0x99}}; - const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]); - HkdfExpandLabel(&k1_, hash_type_, kSessionHash, kHashLength[hash_type_], + const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_)); + HkdfExpandLabel(&k1_, hash_type_, kSessionHash, GetHashLength(hash_type_), kLabelMasterSecret, strlen(kLabelMasterSecret), expected_data); } +TEST_P(TlsHkdfTest, HkdfExpandLabelNoHash) { + const uint8_t tv[][48] = { + {/* ssl_hash_none */}, + {/* ssl_hash_md5 */}, + {/* ssl_hash_sha1 */}, + {/* ssl_hash_sha224 */}, + {0xb7, 0x08, 0x00, 0xe3, 0x8e, 0x48, 0x68, 0x91, 0xb1, 0x0f, 0x5e, + 0x6f, 0x22, 0x53, 0x6b, 0x84, 0x69, 0x75, 0xaa, 0xa3, 0x2a, 0xe7, + 0xde, 0xaa, 0xc3, 0xd1, 0xb4, 0x05, 0x22, 0x5c, 0x68, 0xf5}, + {0x13, 0xd3, 0x36, 0x9f, 0x3c, 0x78, 0xa0, 0x32, 0x40, 0xee, 0x16, 0xe9, + 0x11, 0x12, 0x66, 0xc7, 0x51, 0xad, 0xd8, 0x3c, 0xa1, 0xa3, 0x97, 0x74, + 0xd7, 0x45, 0xff, 0xa7, 0x88, 0x9e, 0x52, 0x17, 0x2e, 0xaa, 0x3a, 0xd2, + 0x35, 0xd8, 0xd5, 0x35, 0xfd, 0x65, 0x70, 0x9f, 0xa9, 0xf9, 0xfa, 0x23}}; + + const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_)); + HkdfExpandLabel(&k1_, hash_type_, nullptr, 0, kLabelMasterSecret, + strlen(kLabelMasterSecret), expected_data); +} + +TEST_P(TlsHkdfTest, BadExtractWrapperInput) { + PK11SymKey* key = nullptr; + + // Bad version. + EXPECT_EQ(SECFailure, + SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256, + k1_.get(), k2_.get(), &key)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + // Bad ciphersuite. + EXPECT_EQ(SECFailure, + SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_NULL_SHA, + k1_.get(), k2_.get(), &key)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + // Old ciphersuite. + EXPECT_EQ(SECFailure, SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3, + TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(), + k2_.get(), &key)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + // NULL outparam.. + EXPECT_EQ(SECFailure, SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3, + TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(), + k2_.get(), nullptr)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + EXPECT_EQ(nullptr, key); +} + +TEST_P(TlsHkdfTest, BadExpandLabelWrapperInput) { + PK11SymKey* key = nullptr; + static const char* kLabel = "label"; + + // Bad version. + EXPECT_EQ( + SECFailure, + SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256, + k1_.get(), nullptr, 0, kLabel, strlen(kLabel), &key)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + // Bad ciphersuite. + EXPECT_EQ( + SECFailure, + SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_NULL_MD5, + k1_.get(), nullptr, 0, kLabel, strlen(kLabel), &key)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + // Old ciphersuite. + EXPECT_EQ(SECFailure, + SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3, + TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(), + nullptr, 0, kLabel, strlen(kLabel), &key)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + // Null PRK. + EXPECT_EQ(SECFailure, SSL_HkdfExpandLabel( + SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256, + nullptr, nullptr, 0, kLabel, strlen(kLabel), &key)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + // Null, non-zero-length handshake hash. + EXPECT_EQ( + SECFailure, + SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256, + k1_.get(), nullptr, 2, kLabel, strlen(kLabel), &key)); + + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + // Null, non-zero-length label. + EXPECT_EQ(SECFailure, + SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3, + TLS_AES_128_GCM_SHA256, k1_.get(), nullptr, 0, + nullptr, strlen(kLabel), &key)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + // Null, empty label. + EXPECT_EQ(SECFailure, SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3, + TLS_AES_128_GCM_SHA256, k1_.get(), + nullptr, 0, nullptr, 0, &key)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + // Null key pointer.. + EXPECT_EQ(SECFailure, + SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3, + TLS_AES_128_GCM_SHA256, k1_.get(), nullptr, 0, + kLabel, strlen(kLabel), nullptr)); + EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); + + EXPECT_EQ(nullptr, key); +} + static const SSLHashType kHashTypes[] = {ssl_hash_sha256, ssl_hash_sha384}; INSTANTIATE_TEST_CASE_P(AllHashFuncs, TlsHkdfTest, ::testing::ValuesIn(kHashTypes)); diff --git a/security/nss/gtests/ssl_gtest/tls_protect.cc b/security/nss/gtests/ssl_gtest/tls_protect.cc index c715a36a6b..de91982f74 100644 --- a/security/nss/gtests/ssl_gtest/tls_protect.cc +++ b/security/nss/gtests/ssl_gtest/tls_protect.cc @@ -5,145 +5,98 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "tls_protect.h" +#include "sslproto.h" #include "tls_filter.h" namespace nss_test { -AeadCipher::~AeadCipher() { - if (key_) { - PK11_FreeSymKey(key_); +static uint64_t FirstSeqno(bool dtls, uint16_t epoc) { + if (dtls) { + return static_cast(epoc) << 48; } + return 0; } -bool AeadCipher::Init(PK11SymKey *key, const uint8_t *iv) { - key_ = PK11_ReferenceSymKey(key); - if (!key_) return false; +TlsCipherSpec::TlsCipherSpec(bool dtls, uint16_t epoc) + : dtls_(dtls), + epoch_(epoc), + in_seqno_(FirstSeqno(dtls, epoc)), + out_seqno_(FirstSeqno(dtls, epoc)) {} - memcpy(iv_, iv, sizeof(iv_)); +bool TlsCipherSpec::SetKeys(SSLCipherSuiteInfo* cipherinfo, + PK11SymKey* secret) { + SSLAeadContext* ctx; + SECStatus rv = SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, + cipherinfo->cipherSuite, secret, "", + 0, // Use the default labels. + &ctx); + if (rv != SECSuccess) { + return false; + } + aead_.reset(ctx); return true; } -void AeadCipher::FormatNonce(uint64_t seq, uint8_t *nonce) { - memcpy(nonce, iv_, 12); - - for (size_t i = 0; i < 8; ++i) { - nonce[12 - (i + 1)] ^= seq & 0xff; - seq >>= 8; +bool TlsCipherSpec::Unprotect(const TlsRecordHeader& header, + const DataBuffer& ciphertext, + DataBuffer* plaintext) { + if (aead_ == nullptr) { + return false; } - - DataBuffer d(nonce, 12); -} - -bool AeadCipher::AeadInner(bool decrypt, void *params, size_t param_length, - const uint8_t *in, size_t inlen, uint8_t *out, - size_t *outlen, size_t maxlen) { - SECStatus rv; - unsigned int uoutlen = 0; - SECItem param = { - siBuffer, static_cast(params), - static_cast(param_length), - }; - - if (decrypt) { - rv = PK11_Decrypt(key_, mech_, ¶m, out, &uoutlen, maxlen, in, inlen); - } else { - rv = PK11_Encrypt(key_, mech_, ¶m, out, &uoutlen, maxlen, in, inlen); - } - *outlen = (int)uoutlen; - - return rv == SECSuccess; -} - -bool AeadCipherAesGcm::Aead(bool decrypt, const uint8_t *hdr, size_t hdr_len, - uint64_t seq, const uint8_t *in, size_t inlen, - uint8_t *out, size_t *outlen, size_t maxlen) { - CK_GCM_PARAMS aeadParams; - unsigned char nonce[12]; - - memset(&aeadParams, 0, sizeof(aeadParams)); - aeadParams.pIv = nonce; - aeadParams.ulIvLen = sizeof(nonce); - aeadParams.pAAD = const_cast(hdr); - aeadParams.ulAADLen = hdr_len; - aeadParams.ulTagBits = 128; - - FormatNonce(seq, nonce); - return AeadInner(decrypt, (unsigned char *)&aeadParams, sizeof(aeadParams), - in, inlen, out, outlen, maxlen); -} - -bool AeadCipherChacha20Poly1305::Aead(bool decrypt, const uint8_t *hdr, - size_t hdr_len, uint64_t seq, - const uint8_t *in, size_t inlen, - uint8_t *out, size_t *outlen, - size_t maxlen) { - CK_NSS_AEAD_PARAMS aeadParams; - unsigned char nonce[12]; - - memset(&aeadParams, 0, sizeof(aeadParams)); - aeadParams.pNonce = nonce; - aeadParams.ulNonceLen = sizeof(nonce); - aeadParams.pAAD = const_cast(hdr); - aeadParams.ulAADLen = hdr_len; - aeadParams.ulTagLen = 16; - - FormatNonce(seq, nonce); - return AeadInner(decrypt, (unsigned char *)&aeadParams, sizeof(aeadParams), - in, inlen, out, outlen, maxlen); -} - -bool TlsCipherSpec::Init(uint16_t epoc, SSLCipherAlgorithm cipher, - PK11SymKey *key, const uint8_t *iv) { - epoch_ = epoc; - switch (cipher) { - case ssl_calg_aes_gcm: - aead_.reset(new AeadCipherAesGcm()); - break; - case ssl_calg_chacha20: - aead_.reset(new AeadCipherChacha20Poly1305()); - break; - default: - return false; - } - - return aead_->Init(key, iv); -} - -bool TlsCipherSpec::Unprotect(const TlsRecordHeader &header, - const DataBuffer &ciphertext, - DataBuffer *plaintext) { // Make space. plaintext->Allocate(ciphertext.len()); auto header_bytes = header.header(); - size_t len; - bool ret = - aead_->Aead(true, header_bytes.data(), header_bytes.len(), - header.sequence_number(), ciphertext.data(), ciphertext.len(), - plaintext->data(), &len, plaintext->len()); - if (!ret) return false; + unsigned int len; + uint64_t seqno; + if (dtls_) { + seqno = header.sequence_number(); + } else { + seqno = in_seqno_; + } + SECStatus rv = + SSL_AeadDecrypt(aead_.get(), seqno, header_bytes.data(), + header_bytes.len(), ciphertext.data(), ciphertext.len(), + plaintext->data(), &len, plaintext->len()); + if (rv != SECSuccess) { + return false; + } - plaintext->Truncate(len); + RecordUnprotected(seqno); + plaintext->Truncate(static_cast(len)); return true; } -bool TlsCipherSpec::Protect(const TlsRecordHeader &header, - const DataBuffer &plaintext, - DataBuffer *ciphertext) { +bool TlsCipherSpec::Protect(const TlsRecordHeader& header, + const DataBuffer& plaintext, + DataBuffer* ciphertext) { + if (aead_ == nullptr) { + return false; + } // Make a padded buffer. - ciphertext->Allocate(plaintext.len() + 32); // Room for any plausible auth tag - size_t len; + unsigned int len; DataBuffer header_bytes; (void)header.WriteHeader(&header_bytes, 0, plaintext.len() + 16); - bool ret = - aead_->Aead(false, header_bytes.data(), header_bytes.len(), - header.sequence_number(), plaintext.data(), plaintext.len(), - ciphertext->data(), &len, ciphertext->len()); - if (!ret) return false; + uint64_t seqno; + if (dtls_) { + seqno = header.sequence_number(); + } else { + seqno = out_seqno_; + } + + SECStatus rv = + SSL_AeadEncrypt(aead_.get(), seqno, header_bytes.data(), + header_bytes.len(), plaintext.data(), plaintext.len(), + ciphertext->data(), &len, ciphertext->len()); + if (rv != SECSuccess) { + return false; + } + + RecordProtected(); ciphertext->Truncate(len); return true; diff --git a/security/nss/gtests/ssl_gtest/tls_protect.h b/security/nss/gtests/ssl_gtest/tls_protect.h index 6f129a4eb6..b1febf8870 100644 --- a/security/nss/gtests/ssl_gtest/tls_protect.h +++ b/security/nss/gtests/ssl_gtest/tls_protect.h @@ -10,71 +10,48 @@ #include #include -#include "databuffer.h" #include "pk11pub.h" #include "sslt.h" +#include "sslexp.h" + +#include "databuffer.h" +#include "scoped_ptrs_ssl.h" namespace nss_test { class TlsRecordHeader; -class AeadCipher { - public: - AeadCipher(CK_MECHANISM_TYPE mech) : mech_(mech), key_(nullptr) {} - virtual ~AeadCipher(); - - bool Init(PK11SymKey *key, const uint8_t *iv); - virtual bool Aead(bool decrypt, const uint8_t *hdr, size_t hdr_len, - uint64_t seq, const uint8_t *in, size_t inlen, uint8_t *out, - size_t *outlen, size_t maxlen) = 0; - - protected: - void FormatNonce(uint64_t seq, uint8_t *nonce); - bool AeadInner(bool decrypt, void *params, size_t param_length, - const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen, - size_t maxlen); - - CK_MECHANISM_TYPE mech_; - PK11SymKey *key_; - uint8_t iv_[12]; -}; - -class AeadCipherChacha20Poly1305 : public AeadCipher { - public: - AeadCipherChacha20Poly1305() : AeadCipher(CKM_NSS_CHACHA20_POLY1305) {} - - protected: - bool Aead(bool decrypt, const uint8_t *hdr, size_t hdr_len, uint64_t seq, - const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen, - size_t maxlen); -}; - -class AeadCipherAesGcm : public AeadCipher { - public: - AeadCipherAesGcm() : AeadCipher(CKM_AES_GCM) {} - - protected: - bool Aead(bool decrypt, const uint8_t *hdr, size_t hdr_len, uint64_t seq, - const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen, - size_t maxlen); -}; - // Our analog of ssl3CipherSpec class TlsCipherSpec { public: - TlsCipherSpec() : epoch_(0), aead_() {} + TlsCipherSpec(bool dtls, uint16_t epoc); + bool SetKeys(SSLCipherSuiteInfo* cipherinfo, PK11SymKey* secret); - bool Init(uint16_t epoch, SSLCipherAlgorithm cipher, PK11SymKey *key, - const uint8_t *iv); + bool Protect(const TlsRecordHeader& header, const DataBuffer& plaintext, + DataBuffer* ciphertext); + bool Unprotect(const TlsRecordHeader& header, const DataBuffer& ciphertext, + DataBuffer* plaintext); - bool Protect(const TlsRecordHeader &header, const DataBuffer &plaintext, - DataBuffer *ciphertext); - bool Unprotect(const TlsRecordHeader &header, const DataBuffer &ciphertext, - DataBuffer *plaintext); uint16_t epoch() const { return epoch_; } + uint64_t next_in_seqno() const { return in_seqno_; } + void RecordUnprotected(uint64_t seqno) { + // Reordering happens, so don't let this go backwards. + in_seqno_ = (std::max)(in_seqno_, seqno + 1); + } + uint64_t next_out_seqno() { return out_seqno_; } + void RecordProtected() { out_seqno_++; } + + void RecordDropped() { record_dropped_ = true; } + bool record_dropped() const { return record_dropped_; } + + bool is_protected() const { return aead_ != nullptr; } private: + bool dtls_; uint16_t epoch_; - std::unique_ptr aead_; + uint64_t in_seqno_; + uint64_t out_seqno_; + bool record_dropped_ = false; + ScopedSSLAeadContext aead_; }; } // namespace nss_test diff --git a/security/nss/help.txt b/security/nss/help.txt index 1df72736e0..210c054b1d 100644 --- a/security/nss/help.txt +++ b/security/nss/help.txt @@ -6,7 +6,7 @@ Usage: build.sh [-h] [-c|-cc] [-v] [-j ] [--gyp|-g] [--opt|-o] [--emit-llvm] [--no-zdefs] [--test] [--ct-verif] [--nspr|--with-nspr=:|--system-nspr] [--system-sqlite] [--enable-fips] [--enable-libpkix] - [--mozpkix-only] + [--mozpkix-only] [-D] This script builds NSS with gyp and ninja. @@ -51,3 +51,4 @@ NSS build tool options: --enable-libpkix make libpkix part of the build --mozpkix-only build only static mozpkix and mozpkix-test libraries support for this build option is limited + -D pass an option directly to gyp diff --git a/security/nss/lib/certdb/cert.h b/security/nss/lib/certdb/cert.h index 333ba4c9dd..1981b8f549 100644 --- a/security/nss/lib/certdb/cert.h +++ b/security/nss/lib/certdb/cert.h @@ -215,6 +215,12 @@ extern void CERT_DestroyCertificate(CERTCertificate *cert); */ extern CERTCertificate *CERT_DupCertificate(CERTCertificate *c); +/* Access the DER of the certificate. This only creates a reference to the DER + * in the outparam not a copy. To avoid the pointer becoming invalid, use + * CERT_DupCertificate() and keep a reference to the duplicate alive. + */ +extern SECStatus CERT_GetCertificateDer(const CERTCertificate *c, SECItem *der); + /* ** Create a new certificate request. This result must be wrapped with an ** CERTSignedData to create a signed certificate request. diff --git a/security/nss/lib/certdb/certdb.c b/security/nss/lib/certdb/certdb.c index 85b5f29170..7eede8d0e1 100644 --- a/security/nss/lib/certdb/certdb.c +++ b/security/nss/lib/certdb/certdb.c @@ -1314,6 +1314,17 @@ CERT_DupCertificate(CERTCertificate *c) return c; } +SECStatus +CERT_GetCertificateDer(const CERTCertificate *c, SECItem *der) +{ + if (!c || !der) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + *der = c->derCert; + return SECSuccess; +} + /* * Allow use of default cert database, so that apps(such as mozilla) don't * have to pass the handle all over the place. diff --git a/security/nss/lib/certhigh/certvfy.c b/security/nss/lib/certhigh/certvfy.c index 3a94a4150c..84b34cd473 100644 --- a/security/nss/lib/certhigh/certvfy.c +++ b/security/nss/lib/certhigh/certvfy.c @@ -37,7 +37,7 @@ CERT_CertTimesValid(CERTCertificate *c) return (valid == secCertTimeValid) ? SECSuccess : SECFailure; } -SECStatus +static SECStatus checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key) { SECStatus rv; @@ -47,6 +47,12 @@ checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key) PRInt32 minLen, len; sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm); + rv = NSS_GetAlgorithmPolicy(sigAlg, &policyFlags); + if (rv == SECSuccess && + !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) { + PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED); + return SECFailure; + } switch (sigAlg) { case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: diff --git a/security/nss/lib/ckfw/builtins/certdata.txt b/security/nss/lib/ckfw/builtins/certdata.txt index 182dda65eb..61ce1dee63 100644 --- a/security/nss/lib/ckfw/builtins/certdata.txt +++ b/security/nss/lib/ckfw/builtins/certdata.txt @@ -23153,3 +23153,678 @@ CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + +# +# Certificate "emSign Root CA - G1" +# +# Issuer: CN=emSign Root CA - G1,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN +# Serial Number:31:f5:e4:62:0c:6c:58:ed:d6:d8 +# Subject: CN=emSign Root CA - G1,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN +# Not Valid Before: Sun Feb 18 18:30:00 2018 +# Not Valid After : Wed Feb 18 18:30:00 2043 +# Fingerprint (SHA-256): 40:F6:AF:03:46:A9:9A:A1:CD:1D:55:5A:4E:9C:CE:62:C7:F9:63:46:03:EE:40:66:15:83:3D:C8:C8:D0:03:67 +# Fingerprint (SHA1): 8A:C7:AD:8F:73:AC:4E:C1:B5:75:4D:A5:40:F4:FC:CF:7C:B5:8E:8C +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "emSign Root CA - G1" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\147\061\013\060\011\006\003\125\004\006\023\002\111\116\061 +\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156 +\040\120\113\111\061\045\060\043\006\003\125\004\012\023\034\145 +\115\165\144\150\162\141\040\124\145\143\150\156\157\154\157\147 +\151\145\163\040\114\151\155\151\164\145\144\061\034\060\032\006 +\003\125\004\003\023\023\145\155\123\151\147\156\040\122\157\157 +\164\040\103\101\040\055\040\107\061 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\147\061\013\060\011\006\003\125\004\006\023\002\111\116\061 +\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156 +\040\120\113\111\061\045\060\043\006\003\125\004\012\023\034\145 +\115\165\144\150\162\141\040\124\145\143\150\156\157\154\157\147 +\151\145\163\040\114\151\155\151\164\145\144\061\034\060\032\006 +\003\125\004\003\023\023\145\155\123\151\147\156\040\122\157\157 +\164\040\103\101\040\055\040\107\061 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\012\061\365\344\142\014\154\130\355\326\330 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\003\224\060\202\002\174\240\003\002\001\002\002\012\061 +\365\344\142\014\154\130\355\326\330\060\015\006\011\052\206\110 +\206\367\015\001\001\013\005\000\060\147\061\013\060\011\006\003 +\125\004\006\023\002\111\116\061\023\060\021\006\003\125\004\013 +\023\012\145\155\123\151\147\156\040\120\113\111\061\045\060\043 +\006\003\125\004\012\023\034\145\115\165\144\150\162\141\040\124 +\145\143\150\156\157\154\157\147\151\145\163\040\114\151\155\151 +\164\145\144\061\034\060\032\006\003\125\004\003\023\023\145\155 +\123\151\147\156\040\122\157\157\164\040\103\101\040\055\040\107 +\061\060\036\027\015\061\070\060\062\061\070\061\070\063\060\060 +\060\132\027\015\064\063\060\062\061\070\061\070\063\060\060\060 +\132\060\147\061\013\060\011\006\003\125\004\006\023\002\111\116 +\061\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147 +\156\040\120\113\111\061\045\060\043\006\003\125\004\012\023\034 +\145\115\165\144\150\162\141\040\124\145\143\150\156\157\154\157 +\147\151\145\163\040\114\151\155\151\164\145\144\061\034\060\032 +\006\003\125\004\003\023\023\145\155\123\151\147\156\040\122\157 +\157\164\040\103\101\040\055\040\107\061\060\202\001\042\060\015 +\006\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001 +\017\000\060\202\001\012\002\202\001\001\000\223\113\273\351\146 +\212\356\235\133\325\064\223\320\033\036\303\347\236\270\144\063 +\177\143\170\150\264\315\056\161\165\327\233\040\306\115\051\274 +\266\150\140\212\367\041\232\126\065\132\363\166\275\330\315\232 +\377\223\126\113\245\131\006\241\223\064\051\335\026\064\165\116 +\362\201\264\307\226\116\255\031\025\122\112\376\074\160\165\160 +\315\257\053\253\025\232\063\074\252\263\213\252\315\103\375\365 +\352\160\377\355\317\021\073\224\316\116\062\026\323\043\100\052 +\167\263\257\074\001\054\154\355\231\054\213\331\116\151\230\262 +\367\217\101\260\062\170\141\326\015\137\303\372\242\100\222\035 +\134\027\346\160\076\065\347\242\267\302\142\342\253\244\070\114 +\265\071\065\157\352\003\151\372\072\124\150\205\155\326\362\057 +\103\125\036\221\015\016\330\325\152\244\226\321\023\074\054\170 +\120\350\072\222\322\027\126\345\065\032\100\034\076\215\054\355 +\071\337\102\340\203\101\164\337\243\315\302\206\140\110\150\343 +\151\013\124\000\213\344\166\151\041\015\171\116\064\010\136\024 +\302\314\261\267\255\327\174\160\212\307\205\002\003\001\000\001 +\243\102\060\100\060\035\006\003\125\035\016\004\026\004\024\373 +\357\015\206\236\260\343\335\251\271\361\041\027\177\076\374\360 +\167\053\032\060\016\006\003\125\035\017\001\001\377\004\004\003 +\002\001\006\060\017\006\003\125\035\023\001\001\377\004\005\060 +\003\001\001\377\060\015\006\011\052\206\110\206\367\015\001\001 +\013\005\000\003\202\001\001\000\131\377\362\214\365\207\175\161 +\075\243\237\033\133\321\332\370\323\234\153\066\275\233\251\141 +\353\336\026\054\164\075\236\346\165\332\327\272\247\274\102\027 +\347\075\221\353\345\175\335\076\234\361\317\222\254\154\110\314 +\302\042\077\151\073\305\266\025\057\243\065\306\150\052\034\127 +\257\071\357\215\320\065\303\030\014\173\000\126\034\315\213\031 +\164\336\276\017\022\340\320\252\241\077\002\064\261\160\316\235 +\030\326\010\003\011\106\356\140\340\176\266\304\111\004\121\175 +\160\140\274\252\262\377\171\162\172\246\035\075\137\052\370\312 +\342\375\071\267\107\271\353\176\337\004\043\257\372\234\006\007 +\351\373\143\223\200\100\265\306\154\012\061\050\316\014\237\317 +\263\043\065\200\101\215\154\304\067\173\201\057\200\241\100\102 +\205\351\331\070\215\350\241\123\315\001\277\151\350\132\006\362 +\105\013\220\372\256\341\277\235\362\256\127\074\245\256\262\126 +\364\213\145\100\351\375\061\201\054\364\071\011\330\356\153\247 +\264\246\035\025\245\230\367\001\201\330\205\175\363\121\134\161 +\210\336\272\314\037\200\176\112 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE + +# Trust for "emSign Root CA - G1" +# Issuer: CN=emSign Root CA - G1,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN +# Serial Number:31:f5:e4:62:0c:6c:58:ed:d6:d8 +# Subject: CN=emSign Root CA - G1,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN +# Not Valid Before: Sun Feb 18 18:30:00 2018 +# Not Valid After : Wed Feb 18 18:30:00 2043 +# Fingerprint (SHA-256): 40:F6:AF:03:46:A9:9A:A1:CD:1D:55:5A:4E:9C:CE:62:C7:F9:63:46:03:EE:40:66:15:83:3D:C8:C8:D0:03:67 +# Fingerprint (SHA1): 8A:C7:AD:8F:73:AC:4E:C1:B5:75:4D:A5:40:F4:FC:CF:7C:B5:8E:8C +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "emSign Root CA - G1" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\212\307\255\217\163\254\116\301\265\165\115\245\100\364\374\317 +\174\265\216\214 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\234\102\204\127\335\313\013\247\056\225\255\266\363\332\274\254 +END +CKA_ISSUER MULTILINE_OCTAL +\060\147\061\013\060\011\006\003\125\004\006\023\002\111\116\061 +\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156 +\040\120\113\111\061\045\060\043\006\003\125\004\012\023\034\145 +\115\165\144\150\162\141\040\124\145\143\150\156\157\154\157\147 +\151\145\163\040\114\151\155\151\164\145\144\061\034\060\032\006 +\003\125\004\003\023\023\145\155\123\151\147\156\040\122\157\157 +\164\040\103\101\040\055\040\107\061 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\012\061\365\344\142\014\154\130\355\326\330 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + +# +# Certificate "emSign ECC Root CA - G3" +# +# Issuer: CN=emSign ECC Root CA - G3,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN +# Serial Number:3c:f6:07:a9:68:70:0e:da:8b:84 +# Subject: CN=emSign ECC Root CA - G3,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN +# Not Valid Before: Sun Feb 18 18:30:00 2018 +# Not Valid After : Wed Feb 18 18:30:00 2043 +# Fingerprint (SHA-256): 86:A1:EC:BA:08:9C:4A:8D:3B:BE:27:34:C6:12:BA:34:1D:81:3E:04:3C:F9:E8:A8:62:CD:5C:57:A3:6B:BE:6B +# Fingerprint (SHA1): 30:43:FA:4F:F2:57:DC:A0:C3:80:EE:2E:58:EA:78:B2:3F:E6:BB:C1 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "emSign ECC Root CA - G3" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\153\061\013\060\011\006\003\125\004\006\023\002\111\116\061 +\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156 +\040\120\113\111\061\045\060\043\006\003\125\004\012\023\034\145 +\115\165\144\150\162\141\040\124\145\143\150\156\157\154\157\147 +\151\145\163\040\114\151\155\151\164\145\144\061\040\060\036\006 +\003\125\004\003\023\027\145\155\123\151\147\156\040\105\103\103 +\040\122\157\157\164\040\103\101\040\055\040\107\063 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\153\061\013\060\011\006\003\125\004\006\023\002\111\116\061 +\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156 +\040\120\113\111\061\045\060\043\006\003\125\004\012\023\034\145 +\115\165\144\150\162\141\040\124\145\143\150\156\157\154\157\147 +\151\145\163\040\114\151\155\151\164\145\144\061\040\060\036\006 +\003\125\004\003\023\027\145\155\123\151\147\156\040\105\103\103 +\040\122\157\157\164\040\103\101\040\055\040\107\063 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\012\074\366\007\251\150\160\016\332\213\204 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\002\116\060\202\001\323\240\003\002\001\002\002\012\074 +\366\007\251\150\160\016\332\213\204\060\012\006\010\052\206\110 +\316\075\004\003\003\060\153\061\013\060\011\006\003\125\004\006 +\023\002\111\116\061\023\060\021\006\003\125\004\013\023\012\145 +\155\123\151\147\156\040\120\113\111\061\045\060\043\006\003\125 +\004\012\023\034\145\115\165\144\150\162\141\040\124\145\143\150 +\156\157\154\157\147\151\145\163\040\114\151\155\151\164\145\144 +\061\040\060\036\006\003\125\004\003\023\027\145\155\123\151\147 +\156\040\105\103\103\040\122\157\157\164\040\103\101\040\055\040 +\107\063\060\036\027\015\061\070\060\062\061\070\061\070\063\060 +\060\060\132\027\015\064\063\060\062\061\070\061\070\063\060\060 +\060\132\060\153\061\013\060\011\006\003\125\004\006\023\002\111 +\116\061\023\060\021\006\003\125\004\013\023\012\145\155\123\151 +\147\156\040\120\113\111\061\045\060\043\006\003\125\004\012\023 +\034\145\115\165\144\150\162\141\040\124\145\143\150\156\157\154 +\157\147\151\145\163\040\114\151\155\151\164\145\144\061\040\060 +\036\006\003\125\004\003\023\027\145\155\123\151\147\156\040\105 +\103\103\040\122\157\157\164\040\103\101\040\055\040\107\063\060 +\166\060\020\006\007\052\206\110\316\075\002\001\006\005\053\201 +\004\000\042\003\142\000\004\043\245\014\270\055\022\365\050\363 +\261\262\335\342\002\022\200\236\071\137\111\115\237\311\045\064 +\131\164\354\273\006\034\347\300\162\257\350\256\057\341\101\124 +\207\024\250\112\262\350\174\202\346\133\152\265\334\263\165\316 +\213\006\320\206\043\277\106\325\216\017\077\004\364\327\034\222 +\176\366\245\143\302\365\137\216\056\117\241\030\031\002\053\062 +\012\202\144\175\026\223\321\243\102\060\100\060\035\006\003\125 +\035\016\004\026\004\024\174\135\002\204\023\324\314\212\233\201 +\316\027\034\056\051\036\234\110\143\102\060\016\006\003\125\035 +\017\001\001\377\004\004\003\002\001\006\060\017\006\003\125\035 +\023\001\001\377\004\005\060\003\001\001\377\060\012\006\010\052 +\206\110\316\075\004\003\003\003\151\000\060\146\002\061\000\276 +\363\141\317\002\020\035\144\225\007\270\030\156\210\205\005\057 +\203\010\027\220\312\037\212\114\350\015\033\172\261\255\325\201 +\011\107\357\073\254\010\004\174\134\231\261\355\107\007\322\002 +\061\000\235\272\125\374\251\112\350\355\355\346\166\001\102\173 +\310\370\140\331\215\121\213\125\073\373\214\173\353\145\011\303 +\370\226\315\107\250\202\362\026\125\167\044\176\022\020\225\004 +\054\243 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE + +# Trust for "emSign ECC Root CA - G3" +# Issuer: CN=emSign ECC Root CA - G3,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN +# Serial Number:3c:f6:07:a9:68:70:0e:da:8b:84 +# Subject: CN=emSign ECC Root CA - G3,O=eMudhra Technologies Limited,OU=emSign PKI,C=IN +# Not Valid Before: Sun Feb 18 18:30:00 2018 +# Not Valid After : Wed Feb 18 18:30:00 2043 +# Fingerprint (SHA-256): 86:A1:EC:BA:08:9C:4A:8D:3B:BE:27:34:C6:12:BA:34:1D:81:3E:04:3C:F9:E8:A8:62:CD:5C:57:A3:6B:BE:6B +# Fingerprint (SHA1): 30:43:FA:4F:F2:57:DC:A0:C3:80:EE:2E:58:EA:78:B2:3F:E6:BB:C1 +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "emSign ECC Root CA - G3" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\060\103\372\117\362\127\334\240\303\200\356\056\130\352\170\262 +\077\346\273\301 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\316\013\162\321\237\210\216\320\120\003\350\343\270\213\147\100 +END +CKA_ISSUER MULTILINE_OCTAL +\060\153\061\013\060\011\006\003\125\004\006\023\002\111\116\061 +\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156 +\040\120\113\111\061\045\060\043\006\003\125\004\012\023\034\145 +\115\165\144\150\162\141\040\124\145\143\150\156\157\154\157\147 +\151\145\163\040\114\151\155\151\164\145\144\061\040\060\036\006 +\003\125\004\003\023\027\145\155\123\151\147\156\040\105\103\103 +\040\122\157\157\164\040\103\101\040\055\040\107\063 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\012\074\366\007\251\150\160\016\332\213\204 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + +# +# Certificate "emSign Root CA - C1" +# +# Issuer: CN=emSign Root CA - C1,O=eMudhra Inc,OU=emSign PKI,C=US +# Serial Number:00:ae:cf:00:ba:c4:cf:32:f8:43:b2 +# Subject: CN=emSign Root CA - C1,O=eMudhra Inc,OU=emSign PKI,C=US +# Not Valid Before: Sun Feb 18 18:30:00 2018 +# Not Valid After : Wed Feb 18 18:30:00 2043 +# Fingerprint (SHA-256): 12:56:09:AA:30:1D:A0:A2:49:B9:7A:82:39:CB:6A:34:21:6F:44:DC:AC:9F:39:54:B1:42:92:F2:E8:C8:60:8F +# Fingerprint (SHA1): E7:2E:F1:DF:FC:B2:09:28:CF:5D:D4:D5:67:37:B1:51:CB:86:4F:01 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "emSign Root CA - C1" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\126\061\013\060\011\006\003\125\004\006\023\002\125\123\061 +\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156 +\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013\145 +\115\165\144\150\162\141\040\111\156\143\061\034\060\032\006\003 +\125\004\003\023\023\145\155\123\151\147\156\040\122\157\157\164 +\040\103\101\040\055\040\103\061 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\126\061\013\060\011\006\003\125\004\006\023\002\125\123\061 +\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156 +\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013\145 +\115\165\144\150\162\141\040\111\156\143\061\034\060\032\006\003 +\125\004\003\023\023\145\155\123\151\147\156\040\122\157\157\164 +\040\103\101\040\055\040\103\061 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\013\000\256\317\000\272\304\317\062\370\103\262 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\003\163\060\202\002\133\240\003\002\001\002\002\013\000 +\256\317\000\272\304\317\062\370\103\262\060\015\006\011\052\206 +\110\206\367\015\001\001\013\005\000\060\126\061\013\060\011\006 +\003\125\004\006\023\002\125\123\061\023\060\021\006\003\125\004 +\013\023\012\145\155\123\151\147\156\040\120\113\111\061\024\060 +\022\006\003\125\004\012\023\013\145\115\165\144\150\162\141\040 +\111\156\143\061\034\060\032\006\003\125\004\003\023\023\145\155 +\123\151\147\156\040\122\157\157\164\040\103\101\040\055\040\103 +\061\060\036\027\015\061\070\060\062\061\070\061\070\063\060\060 +\060\132\027\015\064\063\060\062\061\070\061\070\063\060\060\060 +\132\060\126\061\013\060\011\006\003\125\004\006\023\002\125\123 +\061\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147 +\156\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013 +\145\115\165\144\150\162\141\040\111\156\143\061\034\060\032\006 +\003\125\004\003\023\023\145\155\123\151\147\156\040\122\157\157 +\164\040\103\101\040\055\040\103\061\060\202\001\042\060\015\006 +\011\052\206\110\206\367\015\001\001\001\005\000\003\202\001\017 +\000\060\202\001\012\002\202\001\001\000\317\353\251\271\361\231 +\005\314\330\050\041\112\363\163\064\121\204\126\020\365\240\117 +\054\022\343\372\023\232\047\320\317\371\171\032\164\137\035\171 +\071\374\133\370\160\216\340\222\122\367\344\045\371\124\203\331 +\035\323\310\132\205\077\136\307\266\007\356\076\300\316\232\257 +\254\126\102\052\071\045\160\326\277\265\173\066\255\254\366\163 +\334\315\327\035\212\203\245\373\053\220\025\067\153\034\046\107 +\334\073\051\126\223\152\263\301\152\072\235\075\365\301\227\070 +\130\005\213\034\021\343\344\264\270\135\205\035\203\376\170\137 +\013\105\150\030\110\245\106\163\064\073\376\017\310\166\273\307 +\030\363\005\321\206\363\205\355\347\271\331\062\255\125\210\316 +\246\266\221\260\117\254\176\025\043\226\366\077\360\040\064\026 +\336\012\306\304\004\105\171\177\247\375\276\322\251\245\257\234 +\305\043\052\367\074\041\154\275\257\217\116\305\072\262\363\064 +\022\374\337\200\032\111\244\324\251\225\367\236\211\136\242\211 +\254\224\313\250\150\233\257\212\145\047\315\211\356\335\214\265 +\153\051\160\103\240\151\013\344\271\017\002\003\001\000\001\243 +\102\060\100\060\035\006\003\125\035\016\004\026\004\024\376\241 +\340\160\036\052\003\071\122\132\102\276\134\221\205\172\030\252 +\115\265\060\016\006\003\125\035\017\001\001\377\004\004\003\002 +\001\006\060\017\006\003\125\035\023\001\001\377\004\005\060\003 +\001\001\377\060\015\006\011\052\206\110\206\367\015\001\001\013 +\005\000\003\202\001\001\000\302\112\126\372\025\041\173\050\242 +\351\345\035\373\370\055\304\071\226\101\114\073\047\054\304\154 +\030\025\200\306\254\257\107\131\057\046\013\343\066\260\357\073 +\376\103\227\111\062\231\022\025\133\337\021\051\377\253\123\370 +\273\301\170\017\254\234\123\257\127\275\150\214\075\151\063\360 +\243\240\043\143\073\144\147\042\104\255\325\161\313\126\052\170 +\222\243\117\022\061\066\066\342\336\376\000\304\243\140\017\047 +\255\240\260\212\265\066\172\122\241\275\047\364\040\047\142\350 +\115\224\044\023\344\012\004\351\074\253\056\310\103\011\112\306 +\141\004\345\111\064\176\323\304\310\365\017\300\252\351\272\124 +\136\363\143\053\117\117\120\324\376\271\173\231\214\075\300\056 +\274\002\053\323\304\100\344\212\007\061\036\233\316\046\231\023 +\373\021\352\232\042\014\021\031\307\136\033\201\120\060\310\226 +\022\156\347\313\101\177\221\073\242\107\267\124\200\033\334\000 +\314\232\220\352\303\303\120\006\142\014\060\300\025\110\247\250 +\131\174\341\256\042\242\342\012\172\017\372\142\253\122\114\341 +\361\337\312\276\203\015\102 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE + +# Trust for "emSign Root CA - C1" +# Issuer: CN=emSign Root CA - C1,O=eMudhra Inc,OU=emSign PKI,C=US +# Serial Number:00:ae:cf:00:ba:c4:cf:32:f8:43:b2 +# Subject: CN=emSign Root CA - C1,O=eMudhra Inc,OU=emSign PKI,C=US +# Not Valid Before: Sun Feb 18 18:30:00 2018 +# Not Valid After : Wed Feb 18 18:30:00 2043 +# Fingerprint (SHA-256): 12:56:09:AA:30:1D:A0:A2:49:B9:7A:82:39:CB:6A:34:21:6F:44:DC:AC:9F:39:54:B1:42:92:F2:E8:C8:60:8F +# Fingerprint (SHA1): E7:2E:F1:DF:FC:B2:09:28:CF:5D:D4:D5:67:37:B1:51:CB:86:4F:01 +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "emSign Root CA - C1" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\347\056\361\337\374\262\011\050\317\135\324\325\147\067\261\121 +\313\206\117\001 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\330\343\135\001\041\372\170\132\260\337\272\322\356\052\137\150 +END +CKA_ISSUER MULTILINE_OCTAL +\060\126\061\013\060\011\006\003\125\004\006\023\002\125\123\061 +\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156 +\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013\145 +\115\165\144\150\162\141\040\111\156\143\061\034\060\032\006\003 +\125\004\003\023\023\145\155\123\151\147\156\040\122\157\157\164 +\040\103\101\040\055\040\103\061 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\013\000\256\317\000\272\304\317\062\370\103\262 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + +# +# Certificate "emSign ECC Root CA - C3" +# +# Issuer: CN=emSign ECC Root CA - C3,O=eMudhra Inc,OU=emSign PKI,C=US +# Serial Number:7b:71:b6:82:56:b8:12:7c:9c:a8 +# Subject: CN=emSign ECC Root CA - C3,O=eMudhra Inc,OU=emSign PKI,C=US +# Not Valid Before: Sun Feb 18 18:30:00 2018 +# Not Valid After : Wed Feb 18 18:30:00 2043 +# Fingerprint (SHA-256): BC:4D:80:9B:15:18:9D:78:DB:3E:1D:8C:F4:F9:72:6A:79:5D:A1:64:3C:A5:F1:35:8E:1D:DB:0E:DC:0D:7E:B3 +# Fingerprint (SHA1): B6:AF:43:C2:9B:81:53:7D:F6:EF:6B:C3:1F:1F:60:15:0C:EE:48:66 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "emSign ECC Root CA - C3" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\132\061\013\060\011\006\003\125\004\006\023\002\125\123\061 +\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156 +\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013\145 +\115\165\144\150\162\141\040\111\156\143\061\040\060\036\006\003 +\125\004\003\023\027\145\155\123\151\147\156\040\105\103\103\040 +\122\157\157\164\040\103\101\040\055\040\103\063 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\132\061\013\060\011\006\003\125\004\006\023\002\125\123\061 +\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156 +\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013\145 +\115\165\144\150\162\141\040\111\156\143\061\040\060\036\006\003 +\125\004\003\023\027\145\155\123\151\147\156\040\105\103\103\040 +\122\157\157\164\040\103\101\040\055\040\103\063 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\012\173\161\266\202\126\270\022\174\234\250 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\002\053\060\202\001\261\240\003\002\001\002\002\012\173 +\161\266\202\126\270\022\174\234\250\060\012\006\010\052\206\110 +\316\075\004\003\003\060\132\061\013\060\011\006\003\125\004\006 +\023\002\125\123\061\023\060\021\006\003\125\004\013\023\012\145 +\155\123\151\147\156\040\120\113\111\061\024\060\022\006\003\125 +\004\012\023\013\145\115\165\144\150\162\141\040\111\156\143\061 +\040\060\036\006\003\125\004\003\023\027\145\155\123\151\147\156 +\040\105\103\103\040\122\157\157\164\040\103\101\040\055\040\103 +\063\060\036\027\015\061\070\060\062\061\070\061\070\063\060\060 +\060\132\027\015\064\063\060\062\061\070\061\070\063\060\060\060 +\132\060\132\061\013\060\011\006\003\125\004\006\023\002\125\123 +\061\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147 +\156\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013 +\145\115\165\144\150\162\141\040\111\156\143\061\040\060\036\006 +\003\125\004\003\023\027\145\155\123\151\147\156\040\105\103\103 +\040\122\157\157\164\040\103\101\040\055\040\103\063\060\166\060 +\020\006\007\052\206\110\316\075\002\001\006\005\053\201\004\000 +\042\003\142\000\004\375\245\141\256\173\046\020\035\351\267\042 +\060\256\006\364\201\263\261\102\161\225\071\274\323\122\343\257 +\257\371\362\227\065\222\066\106\016\207\225\215\271\071\132\351 +\273\337\320\376\310\007\101\074\273\125\157\203\243\152\373\142 +\260\201\211\002\160\175\110\305\112\343\351\042\124\042\115\223 +\273\102\014\257\167\234\043\246\175\327\141\021\316\145\307\370 +\177\376\365\362\251\243\102\060\100\060\035\006\003\125\035\016 +\004\026\004\024\373\132\110\320\200\040\100\362\250\351\000\007 +\151\031\167\247\346\303\364\317\060\016\006\003\125\035\017\001 +\001\377\004\004\003\002\001\006\060\017\006\003\125\035\023\001 +\001\377\004\005\060\003\001\001\377\060\012\006\010\052\206\110 +\316\075\004\003\003\003\150\000\060\145\002\061\000\264\330\057 +\002\211\375\266\114\142\272\103\116\023\204\162\265\256\335\034 +\336\326\265\334\126\217\130\100\132\055\336\040\114\042\203\312 +\223\250\176\356\022\100\307\326\207\117\370\337\205\002\060\034 +\024\144\344\174\226\203\021\234\260\321\132\141\113\246\017\111 +\323\000\374\241\374\344\245\377\177\255\327\060\320\307\167\177 +\276\201\007\125\060\120\040\024\365\127\070\012\250\061\121 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE + +# Trust for "emSign ECC Root CA - C3" +# Issuer: CN=emSign ECC Root CA - C3,O=eMudhra Inc,OU=emSign PKI,C=US +# Serial Number:7b:71:b6:82:56:b8:12:7c:9c:a8 +# Subject: CN=emSign ECC Root CA - C3,O=eMudhra Inc,OU=emSign PKI,C=US +# Not Valid Before: Sun Feb 18 18:30:00 2018 +# Not Valid After : Wed Feb 18 18:30:00 2043 +# Fingerprint (SHA-256): BC:4D:80:9B:15:18:9D:78:DB:3E:1D:8C:F4:F9:72:6A:79:5D:A1:64:3C:A5:F1:35:8E:1D:DB:0E:DC:0D:7E:B3 +# Fingerprint (SHA1): B6:AF:43:C2:9B:81:53:7D:F6:EF:6B:C3:1F:1F:60:15:0C:EE:48:66 +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "emSign ECC Root CA - C3" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\266\257\103\302\233\201\123\175\366\357\153\303\037\037\140\025 +\014\356\110\146 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\076\123\263\243\201\356\327\020\370\323\260\035\027\222\365\325 +END +CKA_ISSUER MULTILINE_OCTAL +\060\132\061\013\060\011\006\003\125\004\006\023\002\125\123\061 +\023\060\021\006\003\125\004\013\023\012\145\155\123\151\147\156 +\040\120\113\111\061\024\060\022\006\003\125\004\012\023\013\145 +\115\165\144\150\162\141\040\111\156\143\061\040\060\036\006\003 +\125\004\003\023\027\145\155\123\151\147\156\040\105\103\103\040 +\122\157\157\164\040\103\101\040\055\040\103\063 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\012\173\161\266\202\126\270\022\174\234\250 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + +# +# Certificate "Hongkong Post Root CA 3" +# +# Issuer: CN=Hongkong Post Root CA 3,O=Hongkong Post,L=Hong Kong,ST=Hong Kong,C=HK +# Serial Number:08:16:5f:8a:4c:a5:ec:00:c9:93:40:df:c4:c6:ae:23:b8:1c:5a:a4 +# Subject: CN=Hongkong Post Root CA 3,O=Hongkong Post,L=Hong Kong,ST=Hong Kong,C=HK +# Not Valid Before: Sat Jun 03 02:29:46 2017 +# Not Valid After : Tue Jun 03 02:29:46 2042 +# Fingerprint (SHA-256): 5A:2F:C0:3F:0C:83:B0:90:BB:FA:40:60:4B:09:88:44:6C:76:36:18:3D:F9:84:6E:17:10:1A:44:7F:B8:EF:D6 +# Fingerprint (SHA1): 58:A2:D0:EC:20:52:81:5B:C1:F3:F8:64:02:24:4E:C2:8E:02:4B:02 +CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "Hongkong Post Root CA 3" +CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +CKA_SUBJECT MULTILINE_OCTAL +\060\157\061\013\060\011\006\003\125\004\006\023\002\110\113\061 +\022\060\020\006\003\125\004\010\023\011\110\157\156\147\040\113 +\157\156\147\061\022\060\020\006\003\125\004\007\023\011\110\157 +\156\147\040\113\157\156\147\061\026\060\024\006\003\125\004\012 +\023\015\110\157\156\147\153\157\156\147\040\120\157\163\164\061 +\040\060\036\006\003\125\004\003\023\027\110\157\156\147\153\157 +\156\147\040\120\157\163\164\040\122\157\157\164\040\103\101\040 +\063 +END +CKA_ID UTF8 "0" +CKA_ISSUER MULTILINE_OCTAL +\060\157\061\013\060\011\006\003\125\004\006\023\002\110\113\061 +\022\060\020\006\003\125\004\010\023\011\110\157\156\147\040\113 +\157\156\147\061\022\060\020\006\003\125\004\007\023\011\110\157 +\156\147\040\113\157\156\147\061\026\060\024\006\003\125\004\012 +\023\015\110\157\156\147\153\157\156\147\040\120\157\163\164\061 +\040\060\036\006\003\125\004\003\023\027\110\157\156\147\153\157 +\156\147\040\120\157\163\164\040\122\157\157\164\040\103\101\040 +\063 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\010\026\137\212\114\245\354\000\311\223\100\337\304\306 +\256\043\270\034\132\244 +END +CKA_VALUE MULTILINE_OCTAL +\060\202\005\317\060\202\003\267\240\003\002\001\002\002\024\010 +\026\137\212\114\245\354\000\311\223\100\337\304\306\256\043\270 +\034\132\244\060\015\006\011\052\206\110\206\367\015\001\001\013 +\005\000\060\157\061\013\060\011\006\003\125\004\006\023\002\110 +\113\061\022\060\020\006\003\125\004\010\023\011\110\157\156\147 +\040\113\157\156\147\061\022\060\020\006\003\125\004\007\023\011 +\110\157\156\147\040\113\157\156\147\061\026\060\024\006\003\125 +\004\012\023\015\110\157\156\147\153\157\156\147\040\120\157\163 +\164\061\040\060\036\006\003\125\004\003\023\027\110\157\156\147 +\153\157\156\147\040\120\157\163\164\040\122\157\157\164\040\103 +\101\040\063\060\036\027\015\061\067\060\066\060\063\060\062\062 +\071\064\066\132\027\015\064\062\060\066\060\063\060\062\062\071 +\064\066\132\060\157\061\013\060\011\006\003\125\004\006\023\002 +\110\113\061\022\060\020\006\003\125\004\010\023\011\110\157\156 +\147\040\113\157\156\147\061\022\060\020\006\003\125\004\007\023 +\011\110\157\156\147\040\113\157\156\147\061\026\060\024\006\003 +\125\004\012\023\015\110\157\156\147\153\157\156\147\040\120\157 +\163\164\061\040\060\036\006\003\125\004\003\023\027\110\157\156 +\147\153\157\156\147\040\120\157\163\164\040\122\157\157\164\040 +\103\101\040\063\060\202\002\042\060\015\006\011\052\206\110\206 +\367\015\001\001\001\005\000\003\202\002\017\000\060\202\002\012 +\002\202\002\001\000\263\210\327\352\316\017\040\116\276\346\326 +\003\155\356\131\374\302\127\337\051\150\241\203\016\076\150\307 +\150\130\234\034\140\113\211\103\014\271\324\025\262\356\301\116 +\165\351\265\247\357\345\351\065\231\344\314\034\347\113\137\215 +\063\060\040\063\123\331\246\273\325\076\023\216\351\037\207\111 +\255\120\055\120\312\030\276\001\130\242\023\160\226\273\211\210 +\126\200\134\370\275\054\074\341\114\127\210\273\323\271\225\357 +\313\307\366\332\061\164\050\246\346\124\211\365\101\061\312\345 +\046\032\315\202\340\160\332\073\051\273\325\003\365\231\272\125 +\365\144\321\140\016\263\211\111\270\212\057\005\322\204\105\050 +\174\217\150\120\022\170\374\013\265\123\313\302\230\034\204\243 +\236\260\276\043\244\332\334\310\053\036\332\156\105\036\211\230 +\332\371\000\056\006\351\014\073\160\325\120\045\210\231\313\315 +\163\140\367\325\377\065\147\305\241\274\136\253\315\112\270\105 +\353\310\150\036\015\015\024\106\022\343\322\144\142\212\102\230 +\274\264\306\010\010\370\375\250\114\144\234\166\001\275\057\251 +\154\063\017\330\077\050\270\074\151\001\102\206\176\151\301\311 +\006\312\345\172\106\145\351\302\326\120\101\056\077\267\344\355 +\154\327\277\046\001\021\242\026\051\112\153\064\006\220\354\023 +\322\266\373\152\166\322\074\355\360\326\055\335\341\025\354\243 +\233\057\054\311\076\053\344\151\073\377\162\045\261\066\206\133 +\307\177\153\213\125\033\112\305\040\141\075\256\313\120\341\010 +\072\276\260\217\143\101\123\060\010\131\074\230\035\167\272\143 +\221\172\312\020\120\140\277\360\327\274\225\207\217\227\305\376 +\227\152\001\224\243\174\133\205\035\052\071\072\320\124\241\321 +\071\161\235\375\041\371\265\173\360\342\340\002\217\156\226\044 +\045\054\240\036\054\250\304\211\247\357\355\231\006\057\266\012 +\114\117\333\242\314\067\032\257\107\205\055\212\137\304\064\064 +\114\000\375\030\223\147\023\321\067\346\110\264\213\006\305\127 +\173\031\206\012\171\313\000\311\122\257\102\377\067\217\341\243 +\036\172\075\120\253\143\006\347\025\265\077\266\105\067\224\067 +\261\176\362\110\303\177\305\165\376\227\215\105\217\032\247\032 +\162\050\032\100\017\002\003\001\000\001\243\143\060\141\060\017 +\006\003\125\035\023\001\001\377\004\005\060\003\001\001\377\060 +\016\006\003\125\035\017\001\001\377\004\004\003\002\001\006\060 +\037\006\003\125\035\043\004\030\060\026\200\024\027\235\315\036 +\213\326\071\053\160\323\134\324\240\270\037\260\000\374\305\141 +\060\035\006\003\125\035\016\004\026\004\024\027\235\315\036\213 +\326\071\053\160\323\134\324\240\270\037\260\000\374\305\141\060 +\015\006\011\052\206\110\206\367\015\001\001\013\005\000\003\202 +\002\001\000\126\325\173\156\346\042\001\322\102\233\030\325\016 +\327\146\043\134\343\376\240\307\222\322\351\224\255\113\242\306 +\354\022\174\164\325\110\322\131\024\231\300\353\271\321\353\364 +\110\060\133\255\247\127\163\231\251\323\345\267\321\056\131\044 +\130\334\150\056\056\142\330\152\344\160\013\055\040\120\040\244 +\062\225\321\000\230\273\323\375\367\062\362\111\256\306\172\340 +\107\276\156\316\313\243\162\072\055\151\135\313\310\350\105\071 +\324\372\102\301\021\114\167\135\222\373\152\377\130\104\345\353 +\201\236\257\240\231\255\276\251\001\146\313\070\035\074\337\103 +\037\364\115\156\264\272\027\106\374\175\375\207\201\171\152\015 +\063\017\372\057\370\024\271\200\263\135\115\252\227\341\371\344 +\030\305\370\325\070\214\046\074\375\362\050\342\356\132\111\210 +\054\337\171\075\216\236\220\074\275\101\112\072\335\133\366\232 +\264\316\077\045\060\177\062\175\242\003\224\320\334\172\241\122 +\336\156\223\215\030\046\375\125\254\275\217\233\322\317\257\347 +\206\054\313\037\011\157\243\157\251\204\324\163\277\115\241\164 +\033\116\043\140\362\314\016\252\177\244\234\114\045\250\262\146 +\073\070\377\331\224\060\366\162\204\276\150\125\020\017\306\163 +\054\026\151\223\007\376\261\105\355\273\242\125\152\260\332\265 +\112\002\045\047\205\327\267\267\206\104\026\211\154\200\053\076 +\227\251\234\325\176\125\114\306\336\105\020\034\352\351\073\237 +\003\123\356\356\172\001\002\026\170\324\350\302\276\106\166\210 +\023\077\042\273\110\022\035\122\000\264\002\176\041\032\036\234 +\045\364\363\075\136\036\322\034\371\263\055\266\367\067\134\306 +\313\041\116\260\367\231\107\030\205\301\053\272\125\256\006\352 +\320\007\262\334\253\320\202\226\165\316\322\120\376\231\347\317 +\057\237\347\166\321\141\052\373\041\273\061\320\252\237\107\244 +\262\042\312\026\072\120\127\304\133\103\147\305\145\142\003\111 +\001\353\103\331\330\370\236\255\317\261\143\016\105\364\240\132 +\054\233\055\305\246\300\255\250\107\364\047\114\070\015\056\033 +\111\073\122\364\350\210\203\053\124\050\324\362\065\122\264\062 +\203\142\151\144\014\221\234\237\227\352\164\026\375\037\021\006 +\232\233\364 +END +CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE + +# Trust for "Hongkong Post Root CA 3" +# Issuer: CN=Hongkong Post Root CA 3,O=Hongkong Post,L=Hong Kong,ST=Hong Kong,C=HK +# Serial Number:08:16:5f:8a:4c:a5:ec:00:c9:93:40:df:c4:c6:ae:23:b8:1c:5a:a4 +# Subject: CN=Hongkong Post Root CA 3,O=Hongkong Post,L=Hong Kong,ST=Hong Kong,C=HK +# Not Valid Before: Sat Jun 03 02:29:46 2017 +# Not Valid After : Tue Jun 03 02:29:46 2042 +# Fingerprint (SHA-256): 5A:2F:C0:3F:0C:83:B0:90:BB:FA:40:60:4B:09:88:44:6C:76:36:18:3D:F9:84:6E:17:10:1A:44:7F:B8:EF:D6 +# Fingerprint (SHA1): 58:A2:D0:EC:20:52:81:5B:C1:F3:F8:64:02:24:4E:C2:8E:02:4B:02 +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "Hongkong Post Root CA 3" +CKA_CERT_SHA1_HASH MULTILINE_OCTAL +\130\242\320\354\040\122\201\133\301\363\370\144\002\044\116\302 +\216\002\113\002 +END +CKA_CERT_MD5_HASH MULTILINE_OCTAL +\021\374\237\275\163\060\002\212\375\077\363\130\271\313\040\360 +END +CKA_ISSUER MULTILINE_OCTAL +\060\157\061\013\060\011\006\003\125\004\006\023\002\110\113\061 +\022\060\020\006\003\125\004\010\023\011\110\157\156\147\040\113 +\157\156\147\061\022\060\020\006\003\125\004\007\023\011\110\157 +\156\147\040\113\157\156\147\061\026\060\024\006\003\125\004\012 +\023\015\110\157\156\147\153\157\156\147\040\120\157\163\164\061 +\040\060\036\006\003\125\004\003\023\027\110\157\156\147\153\157 +\156\147\040\120\157\163\164\040\122\157\157\164\040\103\101\040 +\063 +END +CKA_SERIAL_NUMBER MULTILINE_OCTAL +\002\024\010\026\137\212\114\245\354\000\311\223\100\337\304\306 +\256\043\270\034\132\244 +END +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST +CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE diff --git a/security/nss/lib/ckfw/builtins/nssckbi.h b/security/nss/lib/ckfw/builtins/nssckbi.h index 157d9c40df..953c15b0a9 100644 --- a/security/nss/lib/ckfw/builtins/nssckbi.h +++ b/security/nss/lib/ckfw/builtins/nssckbi.h @@ -46,8 +46,8 @@ * It's recommend to switch back to 0 after having reached version 98/99. */ #define NSS_BUILTINS_LIBRARY_VERSION_MAJOR 2 -#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 30 -#define NSS_BUILTINS_LIBRARY_VERSION "2.30" +#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 32 +#define NSS_BUILTINS_LIBRARY_VERSION "2.32" /* These version numbers detail the semantic changes to the ckfw engine. */ #define NSS_BUILTINS_HARDWARE_VERSION_MAJOR 1 diff --git a/security/nss/lib/freebl/blinit.c b/security/nss/lib/freebl/blinit.c index f369e62e71..d1bb037fc1 100644 --- a/security/nss/lib/freebl/blinit.c +++ b/security/nss/lib/freebl/blinit.c @@ -92,23 +92,32 @@ CheckX86CPUSupport() #endif /* NSS_X86_OR_X64 */ /* clang-format off */ -#if (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__) +#if defined(__aarch64__) || defined(__arm__) #ifndef __has_include #define __has_include(x) 0 #endif #if (__has_include() || defined(__linux__)) && \ defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__) +/* This might be conflict with host compiler */ +#if !defined(__ANDROID__) #include +#endif extern unsigned long getauxval(unsigned long type) __attribute__((weak)); #else static unsigned long (*getauxval)(unsigned long) = NULL; -#define AT_HWCAP2 0 -#define AT_HWCAP 0 #endif /* defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__)*/ -#endif /* (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__) */ + +#ifndef AT_HWCAP2 +#define AT_HWCAP2 26 +#endif +#ifndef AT_HWCAP +#define AT_HWCAP 16 +#endif + +#endif /* defined(__aarch64__) || defined(__arm__) */ /* clang-format on */ -#if defined(__aarch64__) && !defined(__ANDROID__) +#if defined(__aarch64__) // Defines from hwcap.h in Linux kernel - ARM64 #ifndef HWCAP_AES #define HWCAP_AES (1 << 3) @@ -138,9 +147,9 @@ CheckARMSupport() /* aarch64 must support NEON. */ arm_neon_support_ = disable_arm_neon == NULL; } -#endif /* defined(__aarch64__) && !defined(__ANDROID__) */ +#endif /* defined(__aarch64__) */ -#if defined(__arm__) && !defined(__ANDROID__) +#if defined(__arm__) // Defines from hwcap.h in Linux kernel - ARM /* * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP @@ -165,23 +174,58 @@ CheckARMSupport() #define HWCAP2_SHA2 (1 << 3) #endif +PRBool +GetNeonSupport() +{ + char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON"); + if (disable_arm_neon) { + return PR_FALSE; + } +#if defined(__ARM_NEON) || defined(__ARM_NEON__) + // Compiler generates NEON instruction as default option. + // If no getauxval, compiler generate NEON instruction by default, + // we should allow NOEN support. + return PR_TRUE; +#elif !defined(__ANDROID__) + // Android's cpu-features.c detects features by the following logic + // + // - Call getauxval(AT_HWCAP) + // - Parse /proc/self/auxv if getauxval is nothing or returns 0 + // - Parse /proc/cpuinfo if both cannot detect features + // + // But we don't use it for Android since Android document + // (https://developer.android.com/ndk/guides/cpu-features) says + // one problem with AT_HWCAP sometimes devices (Nexus 4 and emulator) + // are mistaken for IDIV. + if (getauxval) { + return (getauxval(AT_HWCAP) & HWCAP_NEON); + } +#endif /* defined(__ARM_NEON) || defined(__ARM_NEON__) */ + return PR_FALSE; +} + void CheckARMSupport() { - char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON"); char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES"); if (getauxval) { + // Android's cpu-features.c uses AT_HWCAP2 for newer features. + // AT_HWCAP2 is implemented on newer devices / kernel, so we can trust + // it since cpu-features.c doesn't have workaround / fallback. + // Also, AT_HWCAP2 is supported by glibc 2.18+ on Linux/arm, If + // AT_HWCAP2 isn't supported by glibc or Linux kernel, getauxval will + // returns 0. long hwcaps = getauxval(AT_HWCAP2); arm_aes_support_ = hwcaps & HWCAP2_AES && disable_hw_aes == NULL; arm_pmull_support_ = hwcaps & HWCAP2_PMULL; arm_sha1_support_ = hwcaps & HWCAP2_SHA1; arm_sha2_support_ = hwcaps & HWCAP2_SHA2; - arm_neon_support_ = hwcaps & HWCAP_NEON && disable_arm_neon == NULL; } + arm_neon_support_ = GetNeonSupport(); } -#endif /* defined(__arm__) && !defined(__ANDROID__) */ +#endif /* defined(__arm__) */ -// Enable when Firefox can use it. +// Enable when Firefox can use it for Android API 16 and 17. // #if defined(__ANDROID__) && (defined(__arm__) || defined(__aarch64__)) // #include // void @@ -262,7 +306,7 @@ FreeblInit(void) { #ifdef NSS_X86_OR_X64 CheckX86CPUSupport(); -#elif (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__) +#elif (defined(__aarch64__) || defined(__arm__)) CheckARMSupport(); #endif return PR_SUCCESS; diff --git a/security/nss/lib/freebl/chacha20poly1305.c b/security/nss/lib/freebl/chacha20poly1305.c index 302f0db9e7..7f46827de9 100644 --- a/security/nss/lib/freebl/chacha20poly1305.c +++ b/security/nss/lib/freebl/chacha20poly1305.c @@ -157,6 +157,7 @@ ChaCha20Poly1305_DestroyContext(ChaCha20Poly1305Context *ctx, PRBool freeit) #endif } +#ifndef NSS_DISABLE_CHACHAPOLY void ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k, uint8_t *nonce, uint32_t ctr) @@ -167,6 +168,7 @@ ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k, Hacl_Chacha20_chacha20(output, block, len, k, nonce, ctr); } } +#endif /* NSS_DISABLE_CHACHAPOLY */ SECStatus ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output, diff --git a/security/nss/lib/freebl/crypto_primitives.c b/security/nss/lib/freebl/crypto_primitives.c index 49c8ca5ca6..937e1dd720 100644 --- a/security/nss/lib/freebl/crypto_primitives.c +++ b/security/nss/lib/freebl/crypto_primitives.c @@ -22,7 +22,7 @@ swap8b(PRUint64 value) return (value); } -#elif !defined(_MSC_VER) +#elif !defined(_MSC_VER) && !__has_builtin(__builtin_bswap64) PRUint64 swap8b(PRUint64 x) diff --git a/security/nss/lib/freebl/crypto_primitives.h b/security/nss/lib/freebl/crypto_primitives.h index f19601f4b4..177e6f3fff 100644 --- a/security/nss/lib/freebl/crypto_primitives.h +++ b/security/nss/lib/freebl/crypto_primitives.h @@ -11,6 +11,11 @@ #include #include "prtypes.h" +/* For non-clang platform */ +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + /* Unfortunately this isn't always set when it should be. */ #if defined(HAVE_LONG_LONG) @@ -29,11 +34,16 @@ /* * FREEBL_HTONLL(x): swap bytes in a 64-bit integer. */ +#if defined(IS_LITTLE_ENDIAN) #if defined(_MSC_VER) #pragma intrinsic(_byteswap_uint64) #define FREEBL_HTONLL(x) _byteswap_uint64(x) +#elif __has_builtin(__builtin_bswap64) + +#define FREEBL_HTONLL(x) __builtin_bswap64(x) + #elif defined(__GNUC__) && (defined(__x86_64__) || defined(__x86_64)) PRUint64 swap8b(PRUint64 value); @@ -48,4 +58,8 @@ PRUint64 swap8b(PRUint64 x); #endif /* _MSC_VER */ -#endif /* HAVE_LONG_LONG */ \ No newline at end of file +#else /* IS_LITTLE_ENDIAN */ +#define FREEBL_HTONLL(x) (x) +#endif + +#endif /* HAVE_LONG_LONG */ diff --git a/security/nss/lib/freebl/freebl.gyp b/security/nss/lib/freebl/freebl.gyp index 288ff07a3b..4bc127ce92 100644 --- a/security/nss/lib/freebl/freebl.gyp +++ b/security/nss/lib/freebl/freebl.gyp @@ -76,11 +76,11 @@ '__SSSE3__', ], }], - [ 'OS=="android"', { - # On Android we can't use any of the hardware acceleration :( - 'defines!': [ - '__ARM_NEON__', - '__ARM_NEON', + [ 'target_arch=="arm"', { + # Gecko doesn't support non-NEON platform on Android, but tier-3 + # platform such as Linux/arm will need it + 'cflags_mozilla': [ + '-mfpu=neon' ], }], ], diff --git a/security/nss/lib/freebl/unix_urandom.c b/security/nss/lib/freebl/unix_urandom.c index 869a5ed8cc..720fa80bb7 100644 --- a/security/nss/lib/freebl/unix_urandom.c +++ b/security/nss/lib/freebl/unix_urandom.c @@ -32,7 +32,7 @@ RNG_SystemRNG(void *dest, size_t maxLen) size_t fileBytes = 0; unsigned char *buffer = dest; -#if defined(__OpenBSD__) || (defined(LINUX) && defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25)))) +#if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || (defined(LINUX) && defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25)))) int result; while (fileBytes < maxLen) { diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def index d589fd30e2..53d463a66f 100644 --- a/security/nss/lib/nss/nss.def +++ b/security/nss/lib/nss/nss.def @@ -1145,3 +1145,9 @@ HASH_GetHashOidTagByHashType; ;+ local: ;+ *; ;+}; +;+NSS_3.44 { # NSS 3.44 release +;+ global: +CERT_GetCertificateDer; +;+ local: +;+ *; +;+}; diff --git a/security/nss/lib/nss/nss.h b/security/nss/lib/nss/nss.h index 65a6b631d2..d82b649804 100644 --- a/security/nss/lib/nss/nss.h +++ b/security/nss/lib/nss/nss.h @@ -22,9 +22,9 @@ * The format of the version string should be * ".[.[.]][ ][ ]" */ -#define NSS_VERSION "3.43" _NSS_CUSTOMIZED " Beta" +#define NSS_VERSION "3.44" _NSS_CUSTOMIZED " Beta" #define NSS_VMAJOR 3 -#define NSS_VMINOR 43 +#define NSS_VMINOR 44 #define NSS_VPATCH 0 #define NSS_VBUILD 0 #define NSS_BETA PR_TRUE diff --git a/security/nss/lib/pk11wrap/pk11akey.c b/security/nss/lib/pk11wrap/pk11akey.c index c6070e264d..c36f6ce710 100644 --- a/security/nss/lib/pk11wrap/pk11akey.c +++ b/security/nss/lib/pk11wrap/pk11akey.c @@ -1677,6 +1677,95 @@ PK11_MakeKEAPubKey(unsigned char *keyData, int length) return pubk; } +SECStatus +SECKEY_SetPublicValue(SECKEYPrivateKey *privKey, SECItem *publicValue) +{ + SECStatus rv; + SECKEYPublicKey pubKey; + PLArenaPool *arena; + PK11SlotInfo *slot; + CK_OBJECT_HANDLE privKeyID; + + if (privKey == NULL || publicValue == NULL || + publicValue->data == NULL || publicValue->len == 0) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + pubKey.arena = NULL; + pubKey.keyType = privKey->keyType; + pubKey.pkcs11Slot = NULL; + pubKey.pkcs11ID = CK_INVALID_HANDLE; + /* can't use PORT_InitCheapArena here becase SECKEY_DestroyPublic is used + * to free it, and it uses PORT_FreeArena which not only frees the + * underlying arena, it also frees the allocated arena struct. */ + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + pubKey.arena = arena; + if (arena == NULL) { + return SECFailure; + } + + slot = privKey->pkcs11Slot; + privKeyID = privKey->pkcs11ID; + rv = SECFailure; + switch (privKey->keyType) { + default: + /* error code already set to SECFailure */ + break; + case rsaKey: + pubKey.u.rsa.modulus = *publicValue; + rv = PK11_ReadAttribute(slot, privKeyID, CKA_PUBLIC_EXPONENT, + arena, &pubKey.u.rsa.publicExponent); + break; + case dsaKey: + pubKey.u.dsa.publicValue = *publicValue; + rv = PK11_ReadAttribute(slot, privKeyID, CKA_PRIME, + arena, &pubKey.u.dsa.params.prime); + if (rv != SECSuccess) { + break; + } + rv = PK11_ReadAttribute(slot, privKeyID, CKA_SUBPRIME, + arena, &pubKey.u.dsa.params.subPrime); + if (rv != SECSuccess) { + break; + } + rv = PK11_ReadAttribute(slot, privKeyID, CKA_BASE, + arena, &pubKey.u.dsa.params.base); + break; + case dhKey: + pubKey.u.dh.publicValue = *publicValue; + rv = PK11_ReadAttribute(slot, privKeyID, CKA_PRIME, + arena, &pubKey.u.dh.prime); + if (rv != SECSuccess) { + break; + } + rv = PK11_ReadAttribute(slot, privKeyID, CKA_BASE, + arena, &pubKey.u.dh.base); + break; + case ecKey: + pubKey.u.ec.publicValue = *publicValue; + pubKey.u.ec.encoding = ECPoint_Undefined; + pubKey.u.ec.size = 0; + rv = PK11_ReadAttribute(slot, privKeyID, CKA_EC_PARAMS, + arena, &pubKey.u.ec.DEREncodedParams); + break; + } + if (rv == SECSuccess) { + rv = PK11_ImportPublicKey(slot, &pubKey, PR_TRUE); + } + /* Even though pubKey is stored on the stack, we've allocated + * some of it's data from the arena. SECKEY_DestroyPublicKey + * destroys keys by freeing the arena, so this will clean up all + * the data we allocated specifically for the key above. It will + * also free any slot references which we may have picked up in + * PK11_ImportPublicKey. It won't delete the underlying key if + * its a Token/Permanent key (which it will be if + * PK11_ImportPublicKey succeeds). */ + SECKEY_DestroyPublicKey(&pubKey); + + return rv; +} + /* * NOTE: This function doesn't return a SECKEYPrivateKey struct to represent * the new private key object. If it were to create a session object that @@ -1802,12 +1891,6 @@ try_faulty_3des: nickname, publicValue, isPerm, isPrivate, key_type, usage, usageCount, wincx); if (privKey) { - if (privk) { - *privk = privKey; - } else { - SECKEY_DestroyPrivateKey(privKey); - } - privKey = NULL; rv = SECSuccess; goto done; } @@ -1837,6 +1920,25 @@ try_faulty_3des: rv = SECFailure; done: + if ((rv == SECSuccess) && isPerm) { + /* If we are importing a token object, + * create the corresponding public key. + * If this fails, just continue as the target + * token simply might not support persistant + * public keys. Such tokens are usable, but + * need to be authenticated before searching + * for user certs. */ + (void)SECKEY_SetPublicValue(privKey, publicValue); + } + + if (privKey) { + if (privk) { + *privk = privKey; + } else { + SECKEY_DestroyPrivateKey(privKey); + } + privKey = NULL; + } if (crypto_param != NULL) { SECITEM_ZfreeItem(crypto_param, PR_TRUE); } diff --git a/security/nss/lib/pk11wrap/pk11pars.c b/security/nss/lib/pk11wrap/pk11pars.c index db60f7c9dd..c5e21df519 100644 --- a/security/nss/lib/pk11wrap/pk11pars.c +++ b/security/nss/lib/pk11wrap/pk11pars.c @@ -238,6 +238,8 @@ static const oidValDef curveOptList[] = { NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, { CIPHER_NAME("SECP521R1"), SEC_OID_SECG_EC_SECP521R1, NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, + { CIPHER_NAME("CURVE25519"), SEC_OID_CURVE25519, + NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, /* ANSI X9.62 named elliptic curves (characteristic two field) */ { CIPHER_NAME("C2PNB163V1"), SEC_OID_ANSIX962_EC_C2PNB163V1, NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, @@ -384,18 +386,26 @@ static const oidValDef kxOptList[] = { { CIPHER_NAME("ECDH-RSA"), SEC_OID_TLS_ECDH_RSA, NSS_USE_ALG_IN_SSL_KX }, }; +static const oidValDef signOptList[] = { + /* Signatures */ + { CIPHER_NAME("DSA"), SEC_OID_ANSIX9_DSA_SIGNATURE, + NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE }, +}; + typedef struct { const oidValDef *list; PRUint32 entries; const char *description; + PRBool allowEmpty; } algListsDef; static const algListsDef algOptLists[] = { - { curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC" }, - { hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH" }, - { macOptList, PR_ARRAY_SIZE(macOptList), "MAC" }, - { cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER" }, - { kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX" }, + { curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC", PR_FALSE }, + { hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH", PR_FALSE }, + { macOptList, PR_ARRAY_SIZE(macOptList), "MAC", PR_FALSE }, + { cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER", PR_FALSE }, + { kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX", PR_FALSE }, + { signOptList, PR_ARRAY_SIZE(signOptList), "OTHER-SIGN", PR_TRUE }, }; static const optionFreeDef sslOptList[] = { @@ -718,7 +728,7 @@ secmod_sanityCheckCryptoPolicy(void) for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) { const algListsDef *algOptList = &algOptLists[i]; fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-%s: %u\n", enabledCount[i] ? sInfo : sWarn, algOptList->description, enabledCount[i]); - if (!enabledCount[i]) { + if (!enabledCount[i] && !algOptList->allowEmpty) { haveWarning = PR_TRUE; } } @@ -807,6 +817,10 @@ SECMOD_CreateModuleEx(const char *library, const char *moduleName, mod->internal = NSSUTIL_ArgHasFlag("flags", "internal", nssc); mod->isFIPS = NSSUTIL_ArgHasFlag("flags", "FIPS", nssc); + /* if the system FIPS mode is enabled, force FIPS to be on */ + if (secmod_GetSystemFIPSEnabled()) { + mod->isFIPS = PR_TRUE; + } mod->isCritical = NSSUTIL_ArgHasFlag("flags", "critical", nssc); slotParams = NSSUTIL_ArgGetParamValue("slotParams", nssc); mod->slotInfo = NSSUTIL_ArgParseSlotInfo(mod->arena, slotParams, diff --git a/security/nss/lib/pk11wrap/pk11util.c b/security/nss/lib/pk11wrap/pk11util.c index e316f1f1a2..502c4d00cb 100644 --- a/security/nss/lib/pk11wrap/pk11util.c +++ b/security/nss/lib/pk11wrap/pk11util.c @@ -95,6 +95,31 @@ SECMOD_Shutdown() return SECSuccess; } +int +secmod_GetSystemFIPSEnabled(void) +{ +#ifdef LINUX + FILE *f; + char d; + size_t size; + + f = fopen("/proc/sys/crypto/fips_enabled", "r"); + if (!f) { + return 0; + } + + size = fread(&d, 1, sizeof(d), f); + fclose(f); + if (size != sizeof(d)) { + return 0; + } + if (d == '1') { + return 1; + } +#endif + return 0; +} + /* * retrieve the internal module */ @@ -428,7 +453,7 @@ SECMOD_DeleteInternalModule(const char *name) SECMODModuleList **mlpp; SECStatus rv = SECFailure; - if (pendingModule) { + if (secmod_GetSystemFIPSEnabled() || pendingModule) { PORT_SetError(SEC_ERROR_MODULE_STUCK); return rv; } @@ -963,7 +988,7 @@ SECMOD_CanDeleteInternalModule(void) #ifdef NSS_FIPS_DISABLED return PR_FALSE; #else - return (PRBool)(pendingModule == NULL); + return (PRBool)((pendingModule == NULL) && !secmod_GetSystemFIPSEnabled()); #endif } diff --git a/security/nss/lib/pk11wrap/secmodi.h b/security/nss/lib/pk11wrap/secmodi.h index 7ec77ced60..634b241bdf 100644 --- a/security/nss/lib/pk11wrap/secmodi.h +++ b/security/nss/lib/pk11wrap/secmodi.h @@ -115,6 +115,13 @@ PK11SymKey *pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE pk11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param, SECItem *pwd, PRBool faulty3DES); +/* Get the state of the system FIPS mode */ +/* NSS uses this to force FIPS mode if the system bit is on. Applications which + * use the SECMOD_CanDeleteInteral() to check to see if they can switch to or + * from FIPS mode will automatically be told that they can't swith out of FIPS + * mode */ +int secmod_GetSystemFIPSEnabled(); + extern void pk11sdr_Init(void); extern void pk11sdr_Shutdown(void); diff --git a/security/nss/lib/pkcs7/certread.c b/security/nss/lib/pkcs7/certread.c index 2d692f1a2d..3091f9947e 100644 --- a/security/nss/lib/pkcs7/certread.c +++ b/security/nss/lib/pkcs7/certread.c @@ -492,14 +492,16 @@ typedef struct { static SECStatus collect_certs(void *arg, SECItem **certs, int numcerts) { - SECStatus rv; - collect_args *collectArgs; - - collectArgs = (collect_args *)arg; - - rv = SECITEM_CopyItem(collectArgs->arena, &collectArgs->cert, *certs); - - return (rv); + collect_args *collectArgs = (collect_args *)arg; + if (!collectArgs || !collectArgs->arena) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (numcerts < 1 || !certs || !*certs) { + PORT_SetError(SEC_ERROR_BAD_DER); + return SECFailure; + } + return SECITEM_CopyItem(collectArgs->arena, &collectArgs->cert, *certs); } /* diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index 34f25a9d06..bb86baa69a 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -1815,8 +1815,6 @@ sftk_GetPubKey(SFTKObject *object, CK_KEY_TYPE key_type, break; /* key was not DER encoded, no need to unwrap */ } - PORT_Assert(pubKey->u.ec.ecParams.name != ECCurve25519); - /* handle the encoded case */ if ((pubKey->u.ec.publicValue.data[0] == SEC_ASN1_OCTET_STRING) && pubKey->u.ec.publicValue.len > keyLen) { @@ -1827,7 +1825,13 @@ sftk_GetPubKey(SFTKObject *object, CK_KEY_TYPE key_type, SEC_ASN1_GET(SEC_OctetStringTemplate), &pubKey->u.ec.publicValue); /* nope, didn't decode correctly */ - if ((rv != SECSuccess) || (publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) || (publicValue.len != keyLen)) { + if ((rv != SECSuccess) || (publicValue.len != keyLen)) { + crv = CKR_ATTRIBUTE_VALUE_INVALID; + break; + } + /* we don't handle compressed points except in the case of ECCurve25519 */ + if ((pubKey->u.ec.ecParams.fieldID.type != ec_field_plain) && + (publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED)) { crv = CKR_ATTRIBUTE_VALUE_INVALID; break; } diff --git a/security/nss/lib/softoken/sdb.c b/security/nss/lib/softoken/sdb.c index fb897d68cc..4830bc111f 100644 --- a/security/nss/lib/softoken/sdb.c +++ b/security/nss/lib/softoken/sdb.c @@ -858,7 +858,6 @@ sdb_FindObjectsFinal(SDB *sdb, SDBFind *sdbFind) return sdb_mapSQLError(sdb_p->type, sqlerr); } -static const char GET_ATTRIBUTE_CMD[] = "SELECT ALL %s FROM %s WHERE id=$ID;"; CK_RV sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id, CK_ATTRIBUTE *template, CK_ULONG count) @@ -866,8 +865,6 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id, SDBPrivate *sdb_p = sdb->private; sqlite3 *sqlDB = NULL; sqlite3_stmt *stmt = NULL; - char *getStr = NULL; - char *newStr = NULL; const char *table = NULL; int sqlerr = SQLITE_OK; CK_RV error = CKR_OK; @@ -875,55 +872,74 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id, int retry = 0; unsigned int i; + if (count == 0) { + error = CKR_OBJECT_HANDLE_INVALID; + goto loser; + } + /* open a new db if necessary */ error = sdb_openDBLocal(sdb_p, &sqlDB, &table); if (error != CKR_OK) { goto loser; } + char *columns = NULL; for (i = 0; i < count; i++) { - getStr = sqlite3_mprintf("a%x", template[i].type); - - if (getStr == NULL) { + char *newColumns; + if (columns) { + newColumns = sqlite3_mprintf("%s, a%x", columns, template[i].type); + sqlite3_free(columns); + columns = NULL; + } else { + newColumns = sqlite3_mprintf("a%x", template[i].type); + } + if (!newColumns) { error = CKR_HOST_MEMORY; goto loser; } + columns = newColumns; + } + if (!columns) { + error = CKR_OBJECT_HANDLE_INVALID; + goto loser; + } - newStr = sqlite3_mprintf(GET_ATTRIBUTE_CMD, getStr, table); - sqlite3_free(getStr); - getStr = NULL; - if (newStr == NULL) { - error = CKR_HOST_MEMORY; - goto loser; + char *statement = sqlite3_mprintf("SELECT DISTINCT %s FROM %s where id=$ID LIMIT 1;", + columns, table); + sqlite3_free(columns); + columns = NULL; + if (!statement) { + error = CKR_HOST_MEMORY; + goto loser; + } + + sqlerr = sqlite3_prepare_v2(sqlDB, statement, -1, &stmt, NULL); + sqlite3_free(statement); + statement = NULL; + if (sqlerr != SQLITE_OK) { + goto loser; + } + + // NB: indices in sqlite3_bind_int are 1-indexed + sqlerr = sqlite3_bind_int(stmt, 1, object_id); + if (sqlerr != SQLITE_OK) { + goto loser; + } + + do { + sqlerr = sqlite3_step(stmt); + if (sqlerr == SQLITE_BUSY) { + PR_Sleep(SDB_BUSY_RETRY_TIME); } - - sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL); - sqlite3_free(newStr); - newStr = NULL; - if (sqlerr == SQLITE_ERROR) { - template[i].ulValueLen = -1; - error = CKR_ATTRIBUTE_TYPE_INVALID; - continue; - } else if (sqlerr != SQLITE_OK) { - goto loser; - } - - sqlerr = sqlite3_bind_int(stmt, 1, object_id); - if (sqlerr != SQLITE_OK) { - goto loser; - } - - do { - sqlerr = sqlite3_step(stmt); - if (sqlerr == SQLITE_BUSY) { - PR_Sleep(SDB_BUSY_RETRY_TIME); - } - if (sqlerr == SQLITE_ROW) { + if (sqlerr == SQLITE_ROW) { + PORT_Assert(!found); + for (i = 0; i < count; i++) { unsigned int blobSize; const char *blobData; - blobSize = sqlite3_column_bytes(stmt, 0); - blobData = sqlite3_column_blob(stmt, 0); + // NB: indices in sqlite_column_{bytes,blob} are 0-indexed + blobSize = sqlite3_column_bytes(stmt, i); + blobData = sqlite3_column_blob(stmt, i); if (blobData == NULL) { template[i].ulValueLen = -1; error = CKR_ATTRIBUTE_TYPE_INVALID; @@ -945,13 +961,13 @@ sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id, PORT_Memcpy(template[i].pValue, blobData, blobSize); } template[i].ulValueLen = blobSize; - found = 1; } - } while (!sdb_done(sqlerr, &retry)); - sqlite3_reset(stmt); - sqlite3_finalize(stmt); - stmt = NULL; - } + found = 1; + } + } while (!sdb_done(sqlerr, &retry)); + sqlite3_reset(stmt); + sqlite3_finalize(stmt); + stmt = NULL; loser: /* fix up the error if necessary */ diff --git a/security/nss/lib/softoken/sftkpwd.c b/security/nss/lib/softoken/sftkpwd.c index 9834d3ba01..9f97c77038 100644 --- a/security/nss/lib/softoken/sftkpwd.c +++ b/security/nss/lib/softoken/sftkpwd.c @@ -859,92 +859,77 @@ static CK_RV sftk_updateMacs(PLArenaPool *arena, SFTKDBHandle *handle, CK_OBJECT_HANDLE id, SECItem *newKey) { - CK_ATTRIBUTE authAttrs[] = { - { CKA_MODULUS, NULL, 0 }, - { CKA_PUBLIC_EXPONENT, NULL, 0 }, - { CKA_CERT_SHA1_HASH, NULL, 0 }, - { CKA_CERT_MD5_HASH, NULL, 0 }, - { CKA_TRUST_SERVER_AUTH, NULL, 0 }, - { CKA_TRUST_CLIENT_AUTH, NULL, 0 }, - { CKA_TRUST_EMAIL_PROTECTION, NULL, 0 }, - { CKA_TRUST_CODE_SIGNING, NULL, 0 }, - { CKA_TRUST_STEP_UP_APPROVED, NULL, 0 }, - { CKA_NSS_OVERRIDE_EXTENSIONS, NULL, 0 }, - }; - CK_ULONG authAttrCount = sizeof(authAttrs) / sizeof(CK_ATTRIBUTE); - unsigned int i, count; SFTKDBHandle *keyHandle = handle; SDB *keyTarget = NULL; - - id &= SFTK_OBJ_ID_MASK; - if (handle->type != SFTK_KEYDB_TYPE) { keyHandle = handle->peerDB; } - if (keyHandle == NULL) { return CKR_OK; } - - /* old DB's don't have meta data, finished with MACs */ + // Old DBs don't have metadata, so we can return early here. keyTarget = SFTK_GET_SDB(keyHandle); if ((keyTarget->sdb_flags & SDB_HAS_META) == 0) { return CKR_OK; } - /* - * STEP 1: find the MACed attributes of this object - */ - (void)sftkdb_GetAttributeValue(handle, id, authAttrs, authAttrCount); - count = 0; - /* allocate space for the attributes */ - for (i = 0; i < authAttrCount; i++) { - if ((authAttrs[i].ulValueLen == -1) || (authAttrs[i].ulValueLen == 0)) { + id &= SFTK_OBJ_ID_MASK; + + CK_ATTRIBUTE_TYPE authAttrTypes[] = { + CKA_MODULUS, + CKA_PUBLIC_EXPONENT, + CKA_CERT_SHA1_HASH, + CKA_CERT_MD5_HASH, + CKA_TRUST_SERVER_AUTH, + CKA_TRUST_CLIENT_AUTH, + CKA_TRUST_EMAIL_PROTECTION, + CKA_TRUST_CODE_SIGNING, + CKA_TRUST_STEP_UP_APPROVED, + CKA_NSS_OVERRIDE_EXTENSIONS, + }; + const CK_ULONG authAttrTypeCount = sizeof(authAttrTypes) / sizeof(authAttrTypes[0]); + + // We don't know what attributes this object has, so we update them one at a + // time. + unsigned int i; + for (i = 0; i < authAttrTypeCount; i++) { + CK_ATTRIBUTE authAttr = { authAttrTypes[i], NULL, 0 }; + CK_RV rv = sftkdb_GetAttributeValue(handle, id, &authAttr, 1); + if (rv != CKR_OK) { continue; } - count++; - authAttrs[i].pValue = PORT_ArenaAlloc(arena, authAttrs[i].ulValueLen); - if (authAttrs[i].pValue == NULL) { - break; - } - } - - /* if count was zero, none were found, finished with MACs */ - if (count == 0) { - return CKR_OK; - } - - (void)sftkdb_GetAttributeValue(handle, id, authAttrs, authAttrCount); - /* ignore error code, we expect some possible errors */ - - /* GetAttributeValue just verified the old macs, safe to write - * them out then... */ - for (i = 0; i < authAttrCount; i++) { - SECItem *signText; - SECItem plainText; - SECStatus rv; - - if ((authAttrs[i].ulValueLen == -1) || (authAttrs[i].ulValueLen == 0)) { + if ((authAttr.ulValueLen == -1) || (authAttr.ulValueLen == 0)) { continue; } - - if (authAttrs[i].ulValueLen == sizeof(CK_ULONG) && - sftkdb_isULONGAttribute(authAttrs[i].type)) { - CK_ULONG value = *(CK_ULONG *)authAttrs[i].pValue; - sftk_ULong2SDBULong(authAttrs[i].pValue, value); - authAttrs[i].ulValueLen = SDB_ULONG_SIZE; + authAttr.pValue = PORT_ArenaAlloc(arena, authAttr.ulValueLen); + if (authAttr.pValue == NULL) { + return CKR_HOST_MEMORY; } - - plainText.data = authAttrs[i].pValue; - plainText.len = authAttrs[i].ulValueLen; - rv = sftkdb_SignAttribute(arena, newKey, id, - authAttrs[i].type, &plainText, &signText); - if (rv != SECSuccess) { + rv = sftkdb_GetAttributeValue(handle, id, &authAttr, 1); + if (rv != CKR_OK) { + return rv; + } + if ((authAttr.ulValueLen == -1) || (authAttr.ulValueLen == 0)) { return CKR_GENERAL_ERROR; } - rv = sftkdb_PutAttributeSignature(handle, keyTarget, id, - authAttrs[i].type, signText); - if (rv != SECSuccess) { + // GetAttributeValue just verified the old macs, so it is safe to write + // them out now. + if (authAttr.ulValueLen == sizeof(CK_ULONG) && + sftkdb_isULONGAttribute(authAttr.type)) { + CK_ULONG value = *(CK_ULONG *)authAttr.pValue; + sftk_ULong2SDBULong(authAttr.pValue, value); + authAttr.ulValueLen = SDB_ULONG_SIZE; + } + SECItem *signText; + SECItem plainText; + plainText.data = authAttr.pValue; + plainText.len = authAttr.ulValueLen; + if (sftkdb_SignAttribute(arena, newKey, id, authAttr.type, &plainText, + &signText) != SECSuccess) { + return CKR_GENERAL_ERROR; + } + if (sftkdb_PutAttributeSignature(handle, keyTarget, id, authAttr.type, + signText) != SECSuccess) { return CKR_GENERAL_ERROR; } } @@ -956,110 +941,64 @@ static CK_RV sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb, CK_OBJECT_HANDLE id, SECItem *newKey) { - CK_RV crv = CKR_OK; - CK_RV crv2; - CK_ATTRIBUTE *first, *last; - CK_ATTRIBUTE privAttrs[] = { - { CKA_VALUE, NULL, 0 }, - { CKA_PRIVATE_EXPONENT, NULL, 0 }, - { CKA_PRIME_1, NULL, 0 }, - { CKA_PRIME_2, NULL, 0 }, - { CKA_EXPONENT_1, NULL, 0 }, - { CKA_EXPONENT_2, NULL, 0 }, - { CKA_COEFFICIENT, NULL, 0 } + CK_ATTRIBUTE_TYPE privAttrTypes[] = { + CKA_VALUE, + CKA_PRIVATE_EXPONENT, + CKA_PRIME_1, + CKA_PRIME_2, + CKA_EXPONENT_1, + CKA_EXPONENT_2, + CKA_COEFFICIENT, }; - CK_ULONG privAttrCount = sizeof(privAttrs) / sizeof(CK_ATTRIBUTE); - unsigned int i, count; + const CK_ULONG privAttrCount = sizeof(privAttrTypes) / sizeof(privAttrTypes[0]); - /* - * STEP 1. Read the old attributes in the clear. - */ - - /* Get the attribute sizes. - * ignore the error code, we will have unknown attributes here */ - crv2 = sftkdb_GetAttributeValue(keydb, id, privAttrs, privAttrCount); - - /* - * find the valid block of attributes and fill allocate space for - * their data */ - first = last = NULL; + // We don't know what attributes this object has, so we update them one at a + // time. + unsigned int i; for (i = 0; i < privAttrCount; i++) { - /* find the block of attributes that are appropriate for this - * objects. There should only be once contiguous block, if not - * there's an error. - * - * find the first and last good entry. - */ - if ((privAttrs[i].ulValueLen == -1) || (privAttrs[i].ulValueLen == 0)) { - if (!first) - continue; - if (!last) { - /* previous entry was last good entry */ - last = &privAttrs[i - 1]; - } + // Read the old attribute in the clear. + CK_ATTRIBUTE privAttr = { privAttrTypes[i], NULL, 0 }; + CK_RV crv = sftkdb_GetAttributeValue(keydb, id, &privAttr, 1); + if (crv != CKR_OK) { continue; } - if (!first) { - first = &privAttrs[i]; + if ((privAttr.ulValueLen == -1) || (privAttr.ulValueLen == 0)) { + continue; } - if (last) { - /* OOPS, we've found another good entry beyond the end of the - * last good entry, we need to fail here. */ - crv = CKR_GENERAL_ERROR; - break; + privAttr.pValue = PORT_ArenaAlloc(arena, privAttr.ulValueLen); + if (privAttr.pValue == NULL) { + return CKR_HOST_MEMORY; } - privAttrs[i].pValue = PORT_ArenaAlloc(arena, privAttrs[i].ulValueLen); - if (privAttrs[i].pValue == NULL) { - crv = CKR_HOST_MEMORY; - break; + crv = sftkdb_GetAttributeValue(keydb, id, &privAttr, 1); + if (crv != CKR_OK) { + return crv; } - } - if (first == NULL) { - /* no valid entries found, return error based on crv2 */ - return crv2; - } - if (last == NULL) { - last = &privAttrs[privAttrCount - 1]; - } - if (crv != CKR_OK) { - return crv; - } - /* read the attributes */ - count = (last - first) + 1; - crv = sftkdb_GetAttributeValue(keydb, id, first, count); - if (crv != CKR_OK) { - return crv; - } - - /* - * STEP 2: read the encrypt the attributes with the new key. - */ - for (i = 0; i < count; i++) { - SECItem plainText; - SECItem *result; - SECStatus rv; - - plainText.data = first[i].pValue; - plainText.len = first[i].ulValueLen; - rv = sftkdb_EncryptAttribute(arena, newKey, &plainText, &result); - if (rv != SECSuccess) { + if ((privAttr.ulValueLen == -1) || (privAttr.ulValueLen == 0)) { return CKR_GENERAL_ERROR; } - first[i].pValue = result->data; - first[i].ulValueLen = result->len; - /* clear our sensitive data out */ + SECItem plainText; + SECItem *result; + plainText.data = privAttr.pValue; + plainText.len = privAttr.ulValueLen; + if (sftkdb_EncryptAttribute(arena, newKey, &plainText, &result) != SECSuccess) { + return CKR_GENERAL_ERROR; + } + privAttr.pValue = result->data; + privAttr.ulValueLen = result->len; + // Clear sensitive data. PORT_Memset(plainText.data, 0, plainText.len); + + // Write the newly encrypted attributes out directly. + CK_OBJECT_HANDLE newId = id & SFTK_OBJ_ID_MASK; + keydb->newKey = newKey; + crv = (*keydb->db->sdb_SetAttributeValue)(keydb->db, newId, &privAttr, 1); + keydb->newKey = NULL; + if (crv != CKR_OK) { + return crv; + } } - /* - * STEP 3: write the newly encrypted attributes out directly - */ - id &= SFTK_OBJ_ID_MASK; - keydb->newKey = newKey; - crv = (*keydb->db->sdb_SetAttributeValue)(keydb->db, id, first, count); - keydb->newKey = NULL; - - return crv; + return CKR_OK; } static CK_RV diff --git a/security/nss/lib/softoken/softkver.h b/security/nss/lib/softoken/softkver.h index f58f086a88..5702460254 100644 --- a/security/nss/lib/softoken/softkver.h +++ b/security/nss/lib/softoken/softkver.h @@ -17,9 +17,9 @@ * The format of the version string should be * ".[.[.]][ ][ ]" */ -#define SOFTOKEN_VERSION "3.43" SOFTOKEN_ECC_STRING " Beta" +#define SOFTOKEN_VERSION "3.44" SOFTOKEN_ECC_STRING " Beta" #define SOFTOKEN_VMAJOR 3 -#define SOFTOKEN_VMINOR 43 +#define SOFTOKEN_VMINOR 44 #define SOFTOKEN_VPATCH 0 #define SOFTOKEN_VBUILD 0 #define SOFTOKEN_BETA PR_TRUE diff --git a/security/nss/lib/ssl/dtls13con.c b/security/nss/lib/ssl/dtls13con.c index fdc64c0c84..132b2e3c28 100644 --- a/security/nss/lib/ssl/dtls13con.c +++ b/security/nss/lib/ssl/dtls13con.c @@ -488,7 +488,7 @@ dtls13_HandleAck(sslSocket *ss, sslBuffer *databuf) * for the holddown period to process retransmitted Finisheds. */ if (!ss->sec.isServer && (ss->ssl3.hs.ws == idle_handshake)) { - ssl_CipherSpecReleaseByEpoch(ss, CipherSpecRead, + ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read, TrafficKeyHandshake); } } @@ -515,6 +515,6 @@ dtls13_HolddownTimerCb(sslSocket *ss) { SSL_TRC(10, ("%d: SSL3[%d]: holddown timer fired", SSL_GETPID(), ss->fd)); - ssl_CipherSpecReleaseByEpoch(ss, CipherSpecRead, TrafficKeyHandshake); + ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read, TrafficKeyHandshake); ssl_ClearPRCList(&ss->ssl3.hs.dtlsRcvdHandshake, NULL); } diff --git a/security/nss/lib/ssl/dtlscon.c b/security/nss/lib/ssl/dtlscon.c index a5c604bca3..bbd2f6d79b 100644 --- a/security/nss/lib/ssl/dtlscon.c +++ b/security/nss/lib/ssl/dtlscon.c @@ -542,7 +542,6 @@ dtls_QueueMessage(sslSocket *ss, SSLContentType ct, /* Add DTLS handshake message to the pending queue * Empty the sendBuf buffer. - * This function returns SECSuccess or SECFailure, never SECWouldBlock. * Always set sendBuf.len to 0, even when returning SECFailure. * * Called from: diff --git a/security/nss/lib/ssl/manifest.mn b/security/nss/lib/ssl/manifest.mn index fe9470bd01..201a01049e 100644 --- a/security/nss/lib/ssl/manifest.mn +++ b/security/nss/lib/ssl/manifest.mn @@ -55,6 +55,7 @@ CSRCS = \ tls13replay.c \ sslcert.c \ sslgrp.c \ + sslprimitive.c \ tls13esni.c \ $(NULL) diff --git a/security/nss/lib/ssl/ssl.gyp b/security/nss/lib/ssl/ssl.gyp index 2e28f67757..235f752d5f 100644 --- a/security/nss/lib/ssl/ssl.gyp +++ b/security/nss/lib/ssl/ssl.gyp @@ -35,6 +35,7 @@ 'sslinit.c', 'sslmutex.c', 'sslnonce.c', + 'sslprimitive.c', 'sslreveal.c', 'sslsecur.c', 'sslsnce.c', diff --git a/security/nss/lib/ssl/ssl.h b/security/nss/lib/ssl/ssl.h index fc4a4a70cb..bfeddeff89 100644 --- a/security/nss/lib/ssl/ssl.h +++ b/security/nss/lib/ssl/ssl.h @@ -299,6 +299,17 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd); * This is disabled by default and will be removed in a future version. */ #define SSL_ENABLE_V2_COMPATIBLE_HELLO 38 +/* Enables the post-handshake authentication in TLS 1.3. If it is set + * to PR_TRUE, the client will send the "post_handshake_auth" + * extension to indicate that it will process CertificateRequest + * messages after handshake. + * + * This option applies only to clients. For a server, the + * SSL_SendCertificateRequest can be used to request post-handshake + * authentication. + */ +#define SSL_ENABLE_POST_HANDSHAKE_AUTH 39 + #ifdef SSL_DEPRECATED_FUNCTION /* Old deprecated function names */ SSL_IMPORT SECStatus SSL_Enable(PRFileDesc *fd, int option, PRIntn on); diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index 3b5c69b114..9385e52638 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -64,6 +64,7 @@ static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags); static CK_MECHANISM_TYPE ssl3_GetHashMechanismByHashType(SSLHashType hashType); static CK_MECHANISM_TYPE ssl3_GetMgfMechanismByHashType(SSLHashType hash); PRBool ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme); +PRBool ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme); const PRUint8 ssl_hello_retry_random[] = { 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, @@ -553,10 +554,9 @@ SSL_AtomicIncrementLong(long *x) } } -static PRBool -ssl3_CipherSuiteAllowedForVersionRange( - ssl3CipherSuite cipherSuite, - const SSLVersionRange *vrange) +PRBool +ssl3_CipherSuiteAllowedForVersionRange(ssl3CipherSuite cipherSuite, + const SSLVersionRange *vrange) { switch (cipherSuite) { case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: @@ -912,8 +912,8 @@ count_cipher_suites(sslSocket *ss, PRUint8 policy) * Null compression, mac and encryption functions */ SECStatus -Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen, - const unsigned char *input, int inputLen) +Null_Cipher(void *ctx, unsigned char *output, unsigned int *outputLen, unsigned int maxOutputLen, + const unsigned char *input, unsigned int inputLen) { if (inputLen > maxOutputLen) { *outputLen = 0; /* Match PK11_CipherOp in setting outputLen */ @@ -1394,14 +1394,14 @@ loser: } static SECStatus -ssl3_SetupPendingCipherSpec(sslSocket *ss, CipherSpecDirection direction, +ssl3_SetupPendingCipherSpec(sslSocket *ss, SSLSecretDirection direction, const ssl3CipherSuiteDef *suiteDef, ssl3CipherSpec **specp) { ssl3CipherSpec *spec; const ssl3CipherSpec *prev; - prev = (direction == CipherSpecWrite) ? ss->ssl3.cwSpec : ss->ssl3.crSpec; + prev = (direction == ssl_secret_write) ? ss->ssl3.cwSpec : ss->ssl3.crSpec; if (prev->epoch == PR_UINT16_MAX) { PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED); return SECFailure; @@ -1417,7 +1417,7 @@ ssl3_SetupPendingCipherSpec(sslSocket *ss, CipherSpecDirection direction, spec->epoch = prev->epoch + 1; spec->nextSeqNum = 0; - if (IS_DTLS(ss) && direction == CipherSpecRead) { + if (IS_DTLS(ss) && direction == ssl_secret_read) { dtls_InitRecvdRecords(&spec->recvdRecords); } ssl_SetSpecVersions(ss, spec); @@ -1471,12 +1471,12 @@ ssl3_SetupBothPendingCipherSpecs(sslSocket *ss) ss->ssl3.hs.kea_def = &kea_defs[kea]; PORT_Assert(ss->ssl3.hs.kea_def->kea == kea); - rv = ssl3_SetupPendingCipherSpec(ss, CipherSpecRead, suiteDef, + rv = ssl3_SetupPendingCipherSpec(ss, ssl_secret_read, suiteDef, &ss->ssl3.prSpec); if (rv != SECSuccess) { goto loser; } - rv = ssl3_SetupPendingCipherSpec(ss, CipherSpecWrite, suiteDef, + rv = ssl3_SetupPendingCipherSpec(ss, ssl_secret_write, suiteDef, &ss->ssl3.pwSpec); if (rv != SECSuccess) { goto loser; @@ -1554,15 +1554,15 @@ ssl3_BuildRecordPseudoHeader(DTLSEpoch epoch, } static SECStatus -ssl3_AESGCM(ssl3KeyMaterial *keys, +ssl3_AESGCM(const ssl3KeyMaterial *keys, PRBool doDecrypt, unsigned char *out, - int *outlen, - int maxout, + unsigned int *outlen, + unsigned int maxout, const unsigned char *in, - int inlen, + unsigned int inlen, const unsigned char *additionalData, - int additionalDataLen) + unsigned int additionalDataLen) { SECItem param; SECStatus rv = SECFailure; @@ -1616,11 +1616,11 @@ ssl3_AESGCM(ssl3KeyMaterial *keys, } static SECStatus -ssl3_ChaCha20Poly1305(ssl3KeyMaterial *keys, PRBool doDecrypt, - unsigned char *out, int *outlen, int maxout, - const unsigned char *in, int inlen, +ssl3_ChaCha20Poly1305(const ssl3KeyMaterial *keys, PRBool doDecrypt, + unsigned char *out, unsigned int *outlen, unsigned int maxout, + const unsigned char *in, unsigned int inlen, const unsigned char *additionalData, - int additionalDataLen) + unsigned int additionalDataLen) { size_t i; SECItem param; @@ -1727,7 +1727,7 @@ ssl3_InitPendingContexts(sslSocket *ss, ssl3CipherSpec *spec) spec->cipher = (SSLCipher)PK11_CipherOp; encMechanism = ssl3_Alg2Mech(calg); - encMode = (spec->direction == CipherSpecWrite) ? CKA_ENCRYPT : CKA_DECRYPT; + encMode = (spec->direction == ssl_secret_write) ? CKA_ENCRYPT : CKA_DECRYPT; /* * build the context @@ -2012,7 +2012,7 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec, unsigned int ivLen = 0; unsigned char pseudoHeaderBuf[13]; sslBuffer pseudoHeader = SSL_BUFFER(pseudoHeaderBuf); - int len; + unsigned int len; if (cwSpec->cipherDef->type == type_block && cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { @@ -2130,15 +2130,15 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec, memmove(SSL_BUFFER_NEXT(wrBuf) + p1Len, pIn + p1Len, oddLen); } if (p1Len > 0) { - int cipherBytesPart1 = -1; + unsigned int cipherBytesPart1 = 0; rv = cwSpec->cipher(cwSpec->cipherContext, SSL_BUFFER_NEXT(wrBuf), /* output */ &cipherBytesPart1, /* actual outlen */ p1Len, /* max outlen */ pIn, p1Len); /* input, and inputlen */ - PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int)p1Len); - if (rv != SECSuccess || cipherBytesPart1 != (int)p1Len) { + PORT_Assert(rv == SECSuccess && cipherBytesPart1 == p1Len); + if (rv != SECSuccess || cipherBytesPart1 != p1Len) { PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); return SECFailure; } @@ -2146,15 +2146,15 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec, PORT_Assert(rv == SECSuccess); } if (p2Len > 0) { - int cipherBytesPart2 = -1; + unsigned int cipherBytesPart2 = 0; rv = cwSpec->cipher(cwSpec->cipherContext, SSL_BUFFER_NEXT(wrBuf), &cipherBytesPart2, /* output and actual outLen */ p2Len, /* max outlen */ SSL_BUFFER_NEXT(wrBuf), p2Len); /* input and inputLen*/ - PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int)p2Len); - if (rv != SECSuccess || cipherBytesPart2 != (int)p2Len) { + PORT_Assert(rv == SECSuccess && cipherBytesPart2 == p2Len); + if (rv != SECSuccess || cipherBytesPart2 != p2Len) { PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); return SECFailure; } @@ -2215,7 +2215,7 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSLContentType ct, unsigned int lenOffset; SECStatus rv; - PORT_Assert(cwSpec->direction == CipherSpecWrite); + PORT_Assert(cwSpec->direction == ssl_secret_write); PORT_Assert(SSL_BUFFER_LEN(wrBuf) == 0); PORT_Assert(cwSpec->cipherDef->max_records <= RECORD_SEQ_MAX); @@ -2241,7 +2241,7 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSLContentType ct, #ifdef UNSAFE_FUZZER_MODE { - int len; + unsigned int len; rv = Null_Cipher(NULL, SSL_BUFFER_NEXT(wrBuf), &len, SSL_BUFFER_SPACE(wrBuf), pIn, contentLen); if (rv != SECSuccess) { @@ -2314,8 +2314,8 @@ ssl_ProtectNextRecord(sslSocket *ss, ssl3CipherSpec *spec, SSLContentType ct, * Returns the number of bytes of plaintext that were successfully sent * plus the number of bytes of plaintext that were copied into the * output (write) buffer. - * Returns SECFailure on a hard IO error, memory error, or crypto error. - * Does NOT return SECWouldBlock. + * Returns -1 on an error. PR_WOULD_BLOCK_ERROR is set if the error is blocking + * and not terminal. * * Notes on the use of the private ssl flags: * (no private SSL flags) @@ -2360,13 +2360,26 @@ ssl3_SendRecord(sslSocket *ss, * error, so don't overwrite. */ PORT_SetError(SSL_ERROR_HANDSHAKE_FAILED); } - return SECFailure; + return -1; } /* check for Token Presence */ if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) { PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL); - return SECFailure; + return -1; + } + + if (ss->recordWriteCallback) { + PRUint16 epoch; + ssl_GetSpecReadLock(ss); + epoch = ss->ssl3.cwSpec->epoch; + ssl_ReleaseSpecReadLock(ss); + rv = ss->recordWriteCallback(ss->fd, epoch, ct, pIn, nIn, + ss->recordWriteCallbackArg); + if (rv != SECSuccess) { + return -1; + } + return nIn; } if (cwSpec) { @@ -2470,7 +2483,7 @@ loser: #define SSL3_PENDING_HIGH_WATER 1024 /* Attempt to send the content of "in" in an SSL application_data record. - * Returns "len" or SECFailure, never SECWouldBlock, nor SECSuccess. + * Returns "len" or -1 on failure. */ int ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, @@ -2485,21 +2498,21 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, PORT_Assert(!(flags & ssl_SEND_FLAG_NO_RETRANSMIT)); if (len < 0 || !in) { PORT_SetError(PR_INVALID_ARGUMENT_ERROR); - return SECFailure; + return -1; } if (ss->pendingBuf.len > SSL3_PENDING_HIGH_WATER && !ssl_SocketIsBlocking(ss)) { PORT_Assert(!ssl_SocketIsBlocking(ss)); PORT_SetError(PR_WOULD_BLOCK_ERROR); - return SECFailure; + return -1; } if (ss->appDataBuffered && len) { PORT_Assert(in[0] == (unsigned char)(ss->appDataBuffered)); if (in[0] != (unsigned char)(ss->appDataBuffered)) { PORT_SetError(PR_INVALID_ARGUMENT_ERROR); - return SECFailure; + return -1; } in++; len--; @@ -2548,7 +2561,7 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, PORT_Assert(ss->lastWriteBlocked); break; } - return SECFailure; /* error code set by ssl3_SendRecord */ + return -1; /* error code set by ssl3_SendRecord */ } totalSent += sent; if (ss->pendingBuf.len) { @@ -2577,7 +2590,6 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, } /* Attempt to send buffered handshake messages. - * This function returns SECSuccess or SECFailure, never SECWouldBlock. * Always set sendBuf.len to 0, even when returning SECFailure. * * Depending on whether we are doing DTLS or not, this either calls @@ -2600,7 +2612,6 @@ ssl3_FlushHandshake(sslSocket *ss, PRInt32 flags) } /* Attempt to send the content of sendBuf buffer in an SSL handshake record. - * This function returns SECSuccess or SECFailure, never SECWouldBlock. * Always set sendBuf.len to 0, even when returning SECFailure. * * Called from ssl3_FlushHandshake @@ -4309,6 +4320,22 @@ ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme) return PR_FALSE; } +PRBool +ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme) +{ + switch (scheme) { + case ssl_sig_dsa_sha256: + case ssl_sig_dsa_sha384: + case ssl_sig_dsa_sha512: + case ssl_sig_dsa_sha1: + return PR_TRUE; + + default: + return PR_FALSE; + } + return PR_FALSE; +} + SSLAuthType ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme) { @@ -4956,9 +4983,8 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) } } - if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3 && - type == client_hello_initial) { - rv = tls13_SetupClientHello(ss); + if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3) { + rv = tls13_SetupClientHello(ss, type); if (rv != SECSuccess) { goto loser; } @@ -6021,6 +6047,13 @@ ssl_CanUseSignatureScheme(SSLSignatureScheme scheme, return PR_FALSE; } + if (ssl_IsDsaSignatureScheme(scheme) && + (NSS_GetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, &policy) == + SECSuccess) && + !(policy & NSS_USE_ALG_IN_SSL_KX)) { + return PR_FALSE; + } + hashType = ssl_SignatureSchemeToHashType(scheme); if (requireSha1 && (hashType != ssl_hash_sha1)) { return PR_FALSE; @@ -7382,6 +7415,9 @@ ssl3_CompleteHandleCertificateRequest(sslSocket *ss, if (ss->getClientAuthData != NULL) { PORT_Assert((ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) == ssl_preinfo_all); + PORT_Assert(ss->ssl3.clientPrivateKey == NULL); + PORT_Assert(ss->ssl3.clientCertificate == NULL); + PORT_Assert(ss->ssl3.clientCertChain == NULL); /* XXX Should pass cert_types and algorithms in this call!! */ rv = (SECStatus)(*ss->getClientAuthData)(ss->getClientAuthDataArg, ss->fd, ca_list, @@ -7603,7 +7639,8 @@ ssl3_SendClientSecondRound(sslSocket *ss) " certificate authentication is still pending.", SSL_GETPID(), ss->fd)); ss->ssl3.hs.restartTarget = ssl3_SendClientSecondRound; - return SECWouldBlock; + PORT_SetError(PR_WOULD_BLOCK_ERROR); + return SECFailure; } ssl_GetXmitBufLock(ss); /*******************************/ @@ -8588,6 +8625,45 @@ loser: return SECFailure; } +/* unwrap helper function to handle the case where the wrapKey doesn't wind + * up in the correct token for the master secret */ +PK11SymKey * +ssl_unwrapSymKey(PK11SymKey *wrapKey, + CK_MECHANISM_TYPE wrapType, SECItem *param, + SECItem *wrappedKey, + CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, + int keySize, CK_FLAGS keyFlags, void *pinArg) +{ + PK11SymKey *unwrappedKey; + + /* unwrap the master secret. */ + unwrappedKey = PK11_UnwrapSymKeyWithFlags(wrapKey, wrapType, param, + wrappedKey, target, operation, keySize, + keyFlags); + if (!unwrappedKey) { + PK11SlotInfo *targetSlot = PK11_GetBestSlot(target, pinArg); + PK11SymKey *newWrapKey; + + /* it's possible that we failed to unwrap because the wrapKey is in + * a slot that can't handle target. Move the wrapKey to a slot that + * can handle this mechanism and retry the operation */ + if (targetSlot == NULL) { + return NULL; + } + newWrapKey = PK11_MoveSymKey(targetSlot, CKA_UNWRAP, 0, + PR_FALSE, wrapKey); + PK11_FreeSlot(targetSlot); + if (newWrapKey == NULL) { + return NULL; + } + unwrappedKey = PK11_UnwrapSymKeyWithFlags(newWrapKey, wrapType, param, + wrappedKey, target, operation, keySize, + keyFlags); + PK11_FreeSymKey(newWrapKey); + } + return unwrappedKey; +} + static SECStatus ssl3_UnwrapMasterSecretServer(sslSocket *ss, sslSessionID *sid, PK11SymKey **ms) { @@ -8609,12 +8685,14 @@ ssl3_UnwrapMasterSecretServer(sslSocket *ss, sslSessionID *sid, PK11SymKey **ms) keyFlags = CKF_SIGN | CKF_VERIFY; } - /* unwrap the master secret. */ - *ms = PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, - NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, - CKA_DERIVE, SSL3_MASTER_SECRET_LENGTH, keyFlags); + *ms = ssl_unwrapSymKey(wrapKey, sid->u.ssl3.masterWrapMech, NULL, + &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, + CKA_DERIVE, SSL3_MASTER_SECRET_LENGTH, + keyFlags, ss->pkcs11PinArg); PK11_FreeSymKey(wrapKey); if (!*ms) { + SSL_TRC(10, ("%d: SSL3[%d]: server wrapping key found, but couldn't unwrap MasterSecret. wrapMech=0x%0lx", + SSL_GETPID(), ss->fd, sid->u.ssl3.masterWrapMech)); return SECFailure; } return SECSuccess; @@ -9495,6 +9573,14 @@ ssl3_EncodeSigAlgs(const sslSocket *ss, sslBuffer *buf) continue; } + /* Skip DSA scheme if it is disabled by policy. */ + if (ssl_IsDsaSignatureScheme(ss->ssl3.signatureSchemes[i]) && + (NSS_GetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, &policy) == + SECSuccess) && + !(policy & NSS_USE_ALG_IN_SSL_KX)) { + continue; + } + if ((NSS_GetAlgorithmPolicy(hashOID, &policy) != SECSuccess) || (policy & NSS_USE_ALG_IN_SSL_KX)) { rv = sslBuffer_AppendNumber(buf, ss->ssl3.signatureSchemes[i], 2); @@ -10737,6 +10823,9 @@ ssl3_AuthCertificate(sslSocket *ss) } } + if (ss->sec.ci.sid->peerCert) { + CERT_DestroyCertificate(ss->sec.ci.sid->peerCert); + } ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert); if (!ss->sec.isServer) { @@ -10898,13 +10987,6 @@ ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error) } rv = target(ss); - /* Even if we blocked here, we have accomplished enough to claim - * success. Any remaining work will be taken care of by subsequent - * calls to SSL_ForceHandshake/PR_Send/PR_Read/etc. - */ - if (rv == SECWouldBlock) { - rv = SECSuccess; - } } else { SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race with" " peer's finished message", @@ -11445,7 +11527,8 @@ xmit_loser: } ss->ssl3.hs.restartTarget = ssl3_FinishHandshake; - return SECWouldBlock; + PORT_SetError(PR_WOULD_BLOCK_ERROR); + return SECFailure; } rv = ssl3_FinishHandshake(ss); @@ -11649,9 +11732,10 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length, * authenticate the certificate in ssl3_HandleCertificateStatus. */ rv = ssl3_AuthCertificate(ss); /* sets ss->ssl3.hs.ws */ - PORT_Assert(rv != SECWouldBlock); if (rv != SECSuccess) { - return rv; + /* This can't block. */ + PORT_Assert(PORT_GetError() != PR_WOULD_BLOCK_ERROR); + return SECFailure; } } @@ -11809,28 +11893,17 @@ ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, static SECStatus ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) { - /* - * There may be a partial handshake message already in the handshake - * state. The incoming buffer may contain another portion, or a - * complete message or several messages followed by another portion. - * - * Each message is made contiguous before being passed to the actual - * message parser. - */ - sslBuffer *buf = &ss->ssl3.hs.msgState; /* do not lose the original buffer pointer */ + sslBuffer buf = *origBuf; /* Work from a copy. */ SECStatus rv; PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); - if (buf->buf == NULL) { - *buf = *origBuf; - } - while (buf->len > 0) { + while (buf.len > 0) { if (ss->ssl3.hs.header_bytes < 4) { PRUint8 t; - t = *(buf->buf++); - buf->len--; + t = *(buf.buf++); + buf.len--; if (ss->ssl3.hs.header_bytes++ == 0) ss->ssl3.hs.msg_type = (SSLHandshakeType)t; else @@ -11842,12 +11915,12 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) if (ss->ssl3.hs.msg_len > MAX_HANDSHAKE_MSG_LEN) { (void)ssl3_DecodeError(ss); PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE); - return SECFailure; + goto loser; } #undef MAX_HANDSHAKE_MSG_LEN /* If msg_len is zero, be sure we fall through, - ** even if buf->len is zero. + ** even if buf.len is zero. */ if (ss->ssl3.hs.msg_len > 0) continue; @@ -11858,43 +11931,36 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) * data available for this message. If it can be done right out * of the original buffer, then use it from there. */ - if (ss->ssl3.hs.msg_body.len == 0 && buf->len >= ss->ssl3.hs.msg_len) { + if (ss->ssl3.hs.msg_body.len == 0 && buf.len >= ss->ssl3.hs.msg_len) { /* handle it from input buffer */ - rv = ssl3_HandleHandshakeMessage(ss, buf->buf, ss->ssl3.hs.msg_len, - buf->len == ss->ssl3.hs.msg_len); - if (rv == SECFailure) { - /* This test wants to fall through on either - * SECSuccess or SECWouldBlock. - * ssl3_HandleHandshakeMessage MUST set the error code. - */ - return rv; - } - buf->buf += ss->ssl3.hs.msg_len; - buf->len -= ss->ssl3.hs.msg_len; + rv = ssl3_HandleHandshakeMessage(ss, buf.buf, ss->ssl3.hs.msg_len, + buf.len == ss->ssl3.hs.msg_len); + buf.buf += ss->ssl3.hs.msg_len; + buf.len -= ss->ssl3.hs.msg_len; ss->ssl3.hs.msg_len = 0; ss->ssl3.hs.header_bytes = 0; - if (rv != SECSuccess) { /* return if SECWouldBlock. */ - return rv; + if (rv != SECSuccess) { + goto loser; } } else { /* must be copied to msg_body and dealt with from there */ unsigned int bytes; PORT_Assert(ss->ssl3.hs.msg_body.len < ss->ssl3.hs.msg_len); - bytes = PR_MIN(buf->len, ss->ssl3.hs.msg_len - ss->ssl3.hs.msg_body.len); + bytes = PR_MIN(buf.len, ss->ssl3.hs.msg_len - ss->ssl3.hs.msg_body.len); /* Grow the buffer if needed */ rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, ss->ssl3.hs.msg_len); if (rv != SECSuccess) { /* sslBuffer_Grow has set a memory error code. */ - return SECFailure; + goto loser; } PORT_Memcpy(ss->ssl3.hs.msg_body.buf + ss->ssl3.hs.msg_body.len, - buf->buf, bytes); + buf.buf, bytes); ss->ssl3.hs.msg_body.len += bytes; - buf->buf += bytes; - buf->len -= bytes; + buf.buf += bytes; + buf.len -= bytes; PORT_Assert(ss->ssl3.hs.msg_body.len <= ss->ssl3.hs.msg_len); @@ -11902,30 +11968,33 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) if (ss->ssl3.hs.msg_body.len == ss->ssl3.hs.msg_len) { rv = ssl3_HandleHandshakeMessage( ss, ss->ssl3.hs.msg_body.buf, ss->ssl3.hs.msg_len, - buf->len == 0); - if (rv == SECFailure) { - /* This test wants to fall through on either - * SECSuccess or SECWouldBlock. - * ssl3_HandleHandshakeMessage MUST set error code. - */ - return rv; - } + buf.len == 0); ss->ssl3.hs.msg_body.len = 0; ss->ssl3.hs.msg_len = 0; ss->ssl3.hs.header_bytes = 0; - if (rv != SECSuccess) { /* return if SECWouldBlock. */ - return rv; + if (rv != SECSuccess) { + goto loser; } } else { - PORT_Assert(buf->len == 0); + PORT_Assert(buf.len == 0); break; } } } /* end loop */ origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */ - buf->buf = NULL; /* not a leak. */ return SECSuccess; + +loser : { + /* Make sure to remove any data that was consumed. */ + unsigned int consumed = origBuf->len - buf.len; + PORT_Assert(consumed == buf.buf - origBuf->buf); + if (consumed > 0) { + memmove(origBuf->buf, origBuf->buf + consumed, buf.len); + origBuf->len = buf.len; + } +} + return SECFailure; } /* These macros return the given value with the MSB copied to all the other @@ -12183,7 +12252,7 @@ ssl3_UnprotectRecord(sslSocket *ss, unsigned int hashBytes = MAX_MAC_LENGTH + 1; SECStatus rv; - PORT_Assert(spec->direction == CipherSpecRead); + PORT_Assert(spec->direction == ssl_secret_read); good = ~0U; minLength = spec->macDef->mac_size; @@ -12213,7 +12282,7 @@ ssl3_UnprotectRecord(sslSocket *ss, * discard it before decrypting the rest. */ PRUint8 iv[MAX_IV_LENGTH]; - int decoded; + unsigned int decoded; ivLen = cipher_def->iv_size; if (ivLen < 8 || ivLen > sizeof(iv)) { @@ -12261,12 +12330,12 @@ ssl3_UnprotectRecord(sslSocket *ss, rType, isTLS, rVersion, IS_DTLS(ss), decryptedLen, &header); PORT_Assert(rv == SECSuccess); rv = spec->aead(&spec->keyMaterial, - PR_TRUE, /* do decrypt */ - plaintext->buf, /* out */ - (int *)&plaintext->len, /* outlen */ - plaintext->space, /* maxout */ - cText->buf->buf, /* in */ - cText->buf->len, /* inlen */ + PR_TRUE, /* do decrypt */ + plaintext->buf, /* out */ + &plaintext->len, /* outlen */ + plaintext->space, /* maxout */ + cText->buf->buf, /* in */ + cText->buf->len, /* inlen */ SSL_BUFFER_BASE(&header), SSL_BUFFER_LEN(&header)); if (rv != SECSuccess) { good = 0; @@ -12279,7 +12348,7 @@ ssl3_UnprotectRecord(sslSocket *ss, /* decrypt from cText buf to plaintext. */ rv = spec->cipher( - spec->cipherContext, plaintext->buf, (int *)&plaintext->len, + spec->cipherContext, plaintext->buf, &plaintext->len, plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen); if (rv != SECSuccess) { goto decrypt_loser; @@ -12372,7 +12441,7 @@ ssl3_HandleNonApplicationData(sslSocket *ss, SSLContentType rType, ssl_GetSSL3HandshakeLock(ss); /* All the functions called in this switch MUST set error code if - ** they return SECFailure or SECWouldBlock. + ** they return SECFailure. */ switch (rType) { case ssl_ct_change_cipher_spec: @@ -12429,7 +12498,7 @@ ssl3_GetCipherSpec(sslSocket *ss, SSL3Ciphertext *cText) } if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { /* Try to find the cipher spec. */ - newSpec = ssl_FindCipherSpecByEpoch(ss, CipherSpecRead, + newSpec = ssl_FindCipherSpecByEpoch(ss, ssl_secret_read, epoch); if (newSpec != NULL) { return newSpec; @@ -12561,7 +12630,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText) rv = SECFailure; } else { #ifdef UNSAFE_FUZZER_MODE - rv = Null_Cipher(NULL, plaintext->buf, (int *)&plaintext->len, + rv = Null_Cipher(NULL, plaintext->buf, &plaintext->len, plaintext->space, cText->buf->buf, cText->buf->len); #else /* IMPORTANT: Unprotect functions MUST NOT send alerts @@ -12694,8 +12763,8 @@ ssl3_InitState(sslSocket *ss) ssl_GetSpecWriteLock(ss); PR_INIT_CLIST(&ss->ssl3.hs.cipherSpecs); - rv = ssl_SetupNullCipherSpec(ss, CipherSpecRead); - rv |= ssl_SetupNullCipherSpec(ss, CipherSpecWrite); + rv = ssl_SetupNullCipherSpec(ss, ssl_secret_read); + rv |= ssl_SetupNullCipherSpec(ss, ssl_secret_write); ss->ssl3.pwSpec = ss->ssl3.prSpec = NULL; ssl_ReleaseSpecWriteLock(ss); if (rv != SECSuccess) { diff --git a/security/nss/lib/ssl/ssl3ext.c b/security/nss/lib/ssl/ssl3ext.c index 60b5889e72..e9fc096b73 100644 --- a/security/nss/lib/ssl/ssl3ext.c +++ b/security/nss/lib/ssl/ssl3ext.c @@ -51,6 +51,7 @@ static const ssl3ExtensionHandler clientHelloHandlers[] = { { ssl_tls13_psk_key_exchange_modes_xtn, &tls13_ServerHandlePskModesXtn }, { ssl_tls13_cookie_xtn, &tls13_ServerHandleCookieXtn }, { ssl_tls13_encrypted_sni_xtn, &tls13_ServerHandleEsniXtn }, + { ssl_tls13_post_handshake_auth_xtn, &tls13_ServerHandlePostHandshakeAuthXtn }, { ssl_record_size_limit_xtn, &ssl_HandleRecordSizeLimitXtn }, { 0, NULL } }; @@ -138,6 +139,7 @@ static const sslExtensionBuilder clientHelloSendersTLS[] = { ssl_tls13_cookie_xtn, &tls13_ClientSendHrrCookieXtn }, { ssl_tls13_psk_key_exchange_modes_xtn, &tls13_ClientSendPskModesXtn }, { ssl_tls13_encrypted_sni_xtn, &tls13_ClientSendEsniXtn }, + { ssl_tls13_post_handshake_auth_xtn, &tls13_ClientSendPostHandshakeAuthXtn }, { ssl_record_size_limit_xtn, &ssl_SendRecordSizeLimitXtn }, /* The pre_shared_key extension MUST be last. */ { ssl_tls13_pre_shared_key_xtn, &tls13_ClientSendPreSharedKeyXtn }, diff --git a/security/nss/lib/ssl/ssl3exthandle.c b/security/nss/lib/ssl/ssl3exthandle.c index a2d83fa97a..e25a8f887f 100644 --- a/security/nss/lib/ssl/ssl3exthandle.c +++ b/security/nss/lib/ssl/ssl3exthandle.c @@ -1927,7 +1927,7 @@ ssl_HandleRecordSizeLimitXtn(const sslSocket *ss, TLSExtensionData *xtnData, return SECFailure; } if (data->len != 0 || limit < 64) { - ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter); + ssl3_ExtSendAlert(ss, alert_fatal, decode_error); PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE); return SECFailure; } diff --git a/security/nss/lib/ssl/ssl3gthr.c b/security/nss/lib/ssl/ssl3gthr.c index 64a1878f76..f9c741746f 100644 --- a/security/nss/lib/ssl/ssl3gthr.c +++ b/security/nss/lib/ssl/ssl3gthr.c @@ -389,7 +389,6 @@ dtls_GatherData(sslSocket *ss, sslGather *gs, int flags) * application data is available. * Returns 0 if ssl3_GatherData hits EOF. * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. - * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. * * Called from ssl_GatherRecord1stHandshake in sslcon.c, * and from SSL_ForceHandshake in sslsecur.c @@ -408,7 +407,7 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) SSL_TRC(3, ("%d: SSL3[%d] Cannot gather data; fatal alert already sent", SSL_GETPID(), ss->fd)); PORT_SetError(SSL_ERROR_HANDSHAKE_FAILED); - return SECFailure; + return -1; } SSL_TRC(30, ("%d: SSL3[%d]: ssl3_GatherCompleteHandshake", @@ -422,7 +421,6 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); do { - PRBool handleRecordNow = PR_FALSE; PRBool processingEarlyData; ssl_GetSSL3HandshakeLock(ss); @@ -436,96 +434,82 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) if (ss->ssl3.hs.restartTarget) { ssl_ReleaseSSL3HandshakeLock(ss); PORT_SetError(PR_WOULD_BLOCK_ERROR); - return (int)SECFailure; + return -1; } - /* Treat an empty msgState like a NULL msgState. (Most of the time - * when ssl3_HandleHandshake returns SECWouldBlock, it leaves - * behind a non-NULL but zero-length msgState). - * Test: async_cert_restart_server_sends_hello_request_first_in_separate_record - */ - if (ss->ssl3.hs.msgState.buf) { - if (ss->ssl3.hs.msgState.len == 0) { - ss->ssl3.hs.msgState.buf = NULL; - } else { - handleRecordNow = PR_TRUE; + /* If we have a detached record layer, don't ever gather. */ + if (ss->recordWriteCallback) { + PRBool done = ss->firstHsDone; + ssl_ReleaseSSL3HandshakeLock(ss); + if (done) { + return 1; } + PORT_SetError(PR_WOULD_BLOCK_ERROR); + return -1; } ssl_ReleaseSSL3HandshakeLock(ss); - if (handleRecordNow) { - /* ssl3_HandleHandshake previously returned SECWouldBlock and the - * as-yet-unprocessed plaintext of that previous handshake record. - * We need to process it now before we overwrite it with the next - * handshake record. + /* State for SSLv2 client hello support. */ + ssl2Gather ssl2gs = { PR_FALSE, 0 }; + ssl2Gather *ssl2gs_ptr = NULL; + + /* If we're a server and waiting for a client hello, accept v2. */ + if (ss->sec.isServer && ss->opt.enableV2CompatibleHello && + ss->ssl3.hs.ws == wait_client_hello) { + ssl2gs_ptr = &ssl2gs; + } + + /* bring in the next sslv3 record. */ + if (ss->recvdCloseNotify) { + /* RFC 5246 Section 7.2.1: + * Any data received after a closure alert is ignored. */ - SSL_DBG(("%d: SSL3[%d]: resuming handshake", - SSL_GETPID(), ss->fd)); - PORT_Assert(!IS_DTLS(ss)); - rv = ssl3_HandleNonApplicationData(ss, ssl_ct_handshake, - 0, 0, &ss->gs.buf); + return 0; + } + + if (!IS_DTLS(ss)) { + /* If we're a server waiting for a ClientHello then pass + * ssl2gs to support SSLv2 ClientHello messages. */ + rv = ssl3_GatherData(ss, &ss->gs, flags, ssl2gs_ptr); } else { - /* State for SSLv2 client hello support. */ - ssl2Gather ssl2gs = { PR_FALSE, 0 }; - ssl2Gather *ssl2gs_ptr = NULL; + rv = dtls_GatherData(ss, &ss->gs, flags); - if (ss->sec.isServer && ss->opt.enableV2CompatibleHello && - ss->ssl3.hs.ws == wait_client_hello) { - ssl2gs_ptr = &ssl2gs; + /* If we got a would block error, that means that no data was + * available, so we check the timer to see if it's time to + * retransmit */ + if (rv == SECFailure && + (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) { + dtls_CheckTimer(ss); + /* Restore the error in case something succeeded */ + PORT_SetError(PR_WOULD_BLOCK_ERROR); } + } - /* bring in the next sslv3 record. */ - if (ss->recvdCloseNotify) { - /* RFC 5246 Section 7.2.1: - * Any data received after a closure alert is ignored. - */ - return 0; - } + if (rv <= 0) { + return rv; + } - if (!IS_DTLS(ss)) { - /* Passing a non-NULL ssl2gs here enables detection of - * SSLv2-compatible ClientHello messages. */ - rv = ssl3_GatherData(ss, &ss->gs, flags, ssl2gs_ptr); - } else { - rv = dtls_GatherData(ss, &ss->gs, flags); - - /* If we got a would block error, that means that no data was - * available, so we check the timer to see if it's time to - * retransmit */ - if (rv == SECFailure && - (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) { - dtls_CheckTimer(ss); - /* Restore the error in case something succeeded */ - PORT_SetError(PR_WOULD_BLOCK_ERROR); - } - } - - if (rv <= 0) { + if (ssl2gs.isV2) { + rv = ssl3_HandleV2ClientHello(ss, ss->gs.inbuf.buf, + ss->gs.inbuf.len, + ssl2gs.padding); + if (rv < 0) { return rv; } - - if (ssl2gs.isV2) { - rv = ssl3_HandleV2ClientHello(ss, ss->gs.inbuf.buf, - ss->gs.inbuf.len, - ssl2gs.padding); - if (rv < 0) { - return rv; - } - } else { - /* decipher it, and handle it if it's a handshake. - * If it's application data, ss->gs.buf will not be empty upon return. - * If it's a change cipher spec, alert, or handshake message, - * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess. - * - * cText only needs to be valid for this next function call, so - * it can borrow gs.hdr. - */ - cText.hdr = ss->gs.hdr; - cText.hdrLen = ss->gs.hdrLen; - cText.buf = &ss->gs.inbuf; - rv = ssl3_HandleRecord(ss, &cText); - } + } else { + /* decipher it, and handle it if it's a handshake. + * If it's application data, ss->gs.buf will not be empty upon return. + * If it's a change cipher spec, alert, or handshake message, + * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess. + * + * cText only needs to be valid for this next function call, so + * it can borrow gs.hdr. + */ + cText.hdr = ss->gs.hdr; + cText.hdrLen = ss->gs.hdrLen; + cText.buf = &ss->gs.inbuf; + rv = ssl3_HandleRecord(ss, &cText); } if (rv < 0) { return ss->recvdCloseNotify ? 0 : rv; @@ -575,7 +559,7 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) * delivered to the application before the handshake completes. */ ssl_ReleaseSSL3HandshakeLock(ss); PORT_SetError(PR_WOULD_BLOCK_ERROR); - return SECWouldBlock; + return -1; } ssl_ReleaseSSL3HandshakeLock(ss); } while (keepGoing); @@ -596,7 +580,6 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) * Returns 1 when application data is available. * Returns 0 if ssl3_GatherData hits EOF. * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. - * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. * * Called from DoRecv in sslsecur.c * Caller must hold the recv buf lock. @@ -616,3 +599,109 @@ ssl3_GatherAppDataRecord(sslSocket *ss, int flags) return rv; } + +SECStatus +SSLExp_RecordLayerData(PRFileDesc *fd, PRUint16 epoch, + SSLContentType contentType, + const PRUint8 *data, unsigned int len) +{ + SECStatus rv; + sslSocket *ss = ssl_FindSocket(fd); + if (!ss) { + return SECFailure; + } + if (IS_DTLS(ss) || data == NULL || len == 0) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + /* Run any handshake function. If SSL_RecordLayerData is the only way that + * the handshake is driven, then this is necessary to ensure that + * ssl_BeginClientHandshake or ssl_BeginServerHandshake is called. Note that + * the other function that might be set to ss->handshake, + * ssl3_GatherCompleteHandshake, does nothing when this function is used. */ + ssl_Get1stHandshakeLock(ss); + rv = ssl_Do1stHandshake(ss); + if (rv != SECSuccess && PORT_GetError() != PR_WOULD_BLOCK_ERROR) { + goto early_loser; /* Rely on the existing code. */ + } + + /* Don't allow application data before handshake completion. */ + if (contentType == ssl_ct_application_data && !ss->firstHsDone) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto early_loser; + } + + /* Then we can validate the epoch. */ + PRErrorCode epochError; + ssl_GetSpecReadLock(ss); + if (epoch < ss->ssl3.crSpec->epoch) { + epochError = SEC_ERROR_INVALID_ARGS; /* Too c/old. */ + } else if (epoch > ss->ssl3.crSpec->epoch) { + epochError = PR_WOULD_BLOCK_ERROR; /* Too warm/new. */ + } else { + epochError = 0; /* Just right. */ + } + ssl_ReleaseSpecReadLock(ss); + if (epochError) { + PORT_SetError(epochError); + goto early_loser; + } + + /* If the handshake is still running, we need to run that. */ + ssl_Get1stHandshakeLock(ss); + rv = ssl_Do1stHandshake(ss); + if (rv != SECSuccess && PORT_GetError() != PR_WOULD_BLOCK_ERROR) { + ssl_Release1stHandshakeLock(ss); + return SECFailure; + } + + /* Finally, save the data... */ + ssl_GetRecvBufLock(ss); + rv = sslBuffer_Append(&ss->gs.buf, data, len); + if (rv != SECSuccess) { + goto loser; + } + + /* ...and process it. Just saving application data is enough for it to be + * available to PR_Read(). */ + if (contentType != ssl_ct_application_data) { + rv = ssl3_HandleNonApplicationData(ss, contentType, 0, 0, &ss->gs.buf); + /* This occasionally blocks, but that's OK here. */ + if (rv != SECSuccess && PORT_GetError() != PR_WOULD_BLOCK_ERROR) { + goto loser; + } + } + + ssl_ReleaseRecvBufLock(ss); + ssl_Release1stHandshakeLock(ss); + return SECSuccess; + +loser: + /* Make sure that any data is not used again. */ + ss->gs.buf.len = 0; + ssl_ReleaseRecvBufLock(ss); +early_loser: + ssl_Release1stHandshakeLock(ss); + return SECFailure; +} + +SECStatus +SSLExp_GetCurrentEpoch(PRFileDesc *fd, PRUint16 *readEpoch, + PRUint16 *writeEpoch) +{ + sslSocket *ss = ssl_FindSocket(fd); + if (!ss) { + return SECFailure; + } + + ssl_GetSpecReadLock(ss); + if (readEpoch) { + *readEpoch = ss->ssl3.crSpec->epoch; + } + if (writeEpoch) { + *writeEpoch = ss->ssl3.cwSpec->epoch; + } + ssl_ReleaseSpecReadLock(ss); + return SECSuccess; +} diff --git a/security/nss/lib/ssl/sslcon.c b/security/nss/lib/ssl/sslcon.c index bc63e15371..603da3e158 100644 --- a/security/nss/lib/ssl/sslcon.c +++ b/security/nss/lib/ssl/sslcon.c @@ -44,17 +44,13 @@ const char *ssl_version = "SECURITY_VERSION:" * This function acquires and releases the RecvBufLock. * * returns SECSuccess for success. - * returns SECWouldBlock when that value is returned by - * ssl3_GatherCompleteHandshake(). - * returns SECFailure on all other errors. + * returns SECFailure on error, setting PR_WOULD_BLOCK_ERROR if only blocked. * * The gather functions called by ssl_GatherRecord1stHandshake are expected * to return values interpreted as follows: * 1 : the function completed without error. * 0 : the function read EOF. * -1 : read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. - * -2 : the function wants ssl_GatherRecord1stHandshake to be called again - * immediately, by ssl_Do1stHandshake. * * This code is similar to, and easily confused with, DoRecv() in sslsecur.c * @@ -82,16 +78,14 @@ ssl_GatherRecord1stHandshake(sslSocket *ss) ssl_ReleaseRecvBufLock(ss); if (rv <= 0) { - if (rv == SECWouldBlock) { - /* Progress is blocked waiting for callback completion. */ - SSL_TRC(10, ("%d: SSL[%d]: handshake blocked (need %d)", - SSL_GETPID(), ss->fd, ss->gs.remainder)); - return SECWouldBlock; - } if (rv == 0) { /* EOF. Loser */ PORT_SetError(PR_END_OF_FILE_ERROR); } + if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) { + SSL_TRC(10, ("%d: SSL[%d]: handshake blocked (need %d)", + SSL_GETPID(), ss->fd, ss->gs.remainder)); + } return SECFailure; /* rv is < 0 here. */ } diff --git a/security/nss/lib/ssl/ssldef.c b/security/nss/lib/ssl/ssldef.c index be5bcb2694..3ed1979507 100644 --- a/security/nss/lib/ssl/ssldef.c +++ b/security/nss/lib/ssl/ssldef.c @@ -84,7 +84,7 @@ ssl_DefRecv(sslSocket *ss, unsigned char *buf, int len, int flags) * For blocking sockets, always returns len or SECFailure, no short writes. * For non-blocking sockets: * Returns positive count if any data was written, else returns SECFailure. - * Short writes may occur. Does not return SECWouldBlock. + * Short writes may occur. */ int ssl_DefSend(sslSocket *ss, const unsigned char *buf, int len, int flags) diff --git a/security/nss/lib/ssl/sslerr.h b/security/nss/lib/ssl/sslerr.h index a4aa276576..b8f4e30eaf 100644 --- a/security/nss/lib/ssl/sslerr.h +++ b/security/nss/lib/ssl/sslerr.h @@ -268,6 +268,7 @@ typedef enum { SSL_ERROR_RX_MALFORMED_ESNI_EXTENSION = (SSL_ERROR_BASE + 177), SSL_ERROR_MISSING_ESNI_EXTENSION = (SSL_ERROR_BASE + 178), SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE = (SSL_ERROR_BASE + 179), + SSL_ERROR_MISSING_POST_HANDSHAKE_AUTH_EXTENSION = (SSL_ERROR_BASE + 180), SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */ } SSLErrorCodes; #endif /* NO_SECURITY_ERROR_ENUM */ diff --git a/security/nss/lib/ssl/sslexp.h b/security/nss/lib/ssl/sslexp.h index f450e528dc..d8f050ea57 100644 --- a/security/nss/lib/ssl/sslexp.h +++ b/security/nss/lib/ssl/sslexp.h @@ -350,6 +350,27 @@ typedef SSLHelloRetryRequestAction(PR_CALLBACK *SSLHelloRetryRequestCallback)( (PRFileDesc * _fd, PRBool _requestUpdate), \ (fd, requestUpdate)) +/* This function allows a server application to trigger + * re-authentication (TLS 1.3 only) after handshake. + * + * This function will cause a CertificateRequest message to be sent by + * a server. This can be called once at a time, and is not allowed + * until an answer is received. + * + * The AuthCertificateCallback is called when the answer is received. + * If the answer is accepted by the server, the value returned by + * SSL_PeerCertificate() is replaced. If you need to remember all the + * certificates, you will need to call SSL_PeerCertificate() and save + * what you get before calling this. + * + * If the AuthCertificateCallback returns SECFailure, the connection + * is aborted. + */ +#define SSL_SendCertificateRequest(fd) \ + SSL_EXPERIMENTAL_API("SSL_SendCertificateRequest", \ + (PRFileDesc * _fd), \ + (fd)) + /* * Session cache API. */ @@ -511,6 +532,197 @@ typedef SECStatus(PR_CALLBACK *SSLResumptionTokenCallback)( group, pubKey, pad, notBefore, notAfter, \ out, outlen, maxlen)) +/* SSL_SetSecretCallback installs a callback that TLS calls when it installs new + * traffic secrets. + * + * SSLSecretCallback is called with the current epoch and the corresponding + * secret; this matches the epoch used in DTLS 1.3, even if the socket is + * operating in stream mode: + * + * - client_early_traffic_secret corresponds to epoch 1 + * - {client|server}_handshake_traffic_secret is epoch 2 + * - {client|server}_application_traffic_secret_{N} is epoch 3+N + * + * The callback is invoked separately for read secrets (client secrets on the + * server; server secrets on the client), and write secrets. + * + * This callback is only called if (D)TLS 1.3 is negotiated. + */ +typedef void(PR_CALLBACK *SSLSecretCallback)( + PRFileDesc *fd, PRUint16 epoch, SSLSecretDirection dir, PK11SymKey *secret, + void *arg); + +#define SSL_SecretCallback(fd, cb, arg) \ + SSL_EXPERIMENTAL_API("SSL_SecretCallback", \ + (PRFileDesc * _fd, SSLSecretCallback _cb, void *_arg), \ + (fd, cb, arg)) + +/* SSL_RecordLayerWriteCallback() is used to replace the TLS record layer. This + * function installs a callback that TLS calls when it would otherwise encrypt + * and write a record to the underlying NSPR IO layer. The application is + * responsible for ensuring that these records are encrypted and written. + * + * Calling this API also disables reads from the underlying NSPR layer. The + * application is expected to push data when it is available using + * SSL_RecordLayerData(). + * + * When data would be written, the provided SSLRecordWriteCallback with the + * epoch, TLS content type, and the data. The data provided to the callback is + * not split into record-sized writes. If the callback returns SECFailure, the + * write will be considered to have failed; in particular, PR_WOULD_BLOCK_ERROR + * is not handled specially. + * + * If TLS 1.3 is in use, the epoch indicates the expected level of protection + * that the record would receive, this matches that used in DTLS 1.3: + * + * - epoch 0 corresponds to no record protection + * - epoch 1 corresponds to 0-RTT + * - epoch 2 corresponds to TLS handshake + * - epoch 3 and higher are application data + * + * Prior versions of TLS use epoch 1 and higher for application data. + * + * This API is not supported for DTLS. + */ +typedef SECStatus(PR_CALLBACK *SSLRecordWriteCallback)( + PRFileDesc *fd, PRUint16 epoch, SSLContentType contentType, + const PRUint8 *data, unsigned int len, void *arg); + +#define SSL_RecordLayerWriteCallback(fd, writeCb, arg) \ + SSL_EXPERIMENTAL_API("SSL_RecordLayerWriteCallback", \ + (PRFileDesc * _fd, SSLRecordWriteCallback _wCb, \ + void *_arg), \ + (fd, writeCb, arg)) + +/* SSL_RecordLayerData() is used to provide new data to TLS. The application + * indicates the epoch (see the description of SSL_RecordLayerWriteCallback()), + * content type, and the data that was received. The application is responsible + * for removing any encryption or other protection before passing data to this + * function. + * + * This returns SECSuccess if the data was successfully processed. If this + * function is used to drive the handshake and the caller needs to know when the + * handshake is complete, a call to SSL_ForceHandshake will return SECSuccess + * when the handshake is complete. + * + * This API is not supported for DTLS sockets. + */ +#define SSL_RecordLayerData(fd, epoch, ct, data, len) \ + SSL_EXPERIMENTAL_API("SSL_RecordLayerData", \ + (PRFileDesc * _fd, PRUint16 _epoch, \ + SSLContentType _contentType, \ + const PRUint8 *_data, unsigned int _len), \ + (fd, epoch, ct, data, len)) + +/* + * SSL_GetCurrentEpoch() returns the read and write epochs that the socket is + * currently using. NULL values for readEpoch or writeEpoch are ignored. + * + * See SSL_RecordLayerWriteCallback() for details on epochs. + */ +#define SSL_GetCurrentEpoch(fd, readEpoch, writeEpoch) \ + SSL_EXPERIMENTAL_API("SSL_GetCurrentEpoch", \ + (PRFileDesc * _fd, PRUint16 * _readEpoch, \ + PRUint16 * _writeEpoch), \ + (fd, readEpoch, writeEpoch)) + +/* + * The following AEAD functions expose an AEAD primitive that uses a ciphersuite + * to set parameters. The ciphersuite determines the Hash function used by + * HKDF, the AEAD function, and the size of key and IV. This is only supported + * for TLS 1.3. + * + * The key and IV are generated using the TLS KDF with a custom label. That is + * HKDF-Expand-Label(secret, labelPrefix + " key" or " iv", "", L). + * + * The encrypt and decrypt functions use a nonce construction identical to that + * used in TLS. The lower bits of the IV are XORed with the 64-bit counter to + * produce the nonce. Otherwise, this is an AEAD interface similar to that + * described in RFC 5116. + */ +typedef struct SSLAeadContextStr SSLAeadContext; + +#define SSL_MakeAead(version, cipherSuite, secret, \ + labelPrefix, labelPrefixLen, ctx) \ + SSL_EXPERIMENTAL_API("SSL_MakeAead", \ + (PRUint16 _version, PRUint16 _cipherSuite, \ + PK11SymKey * _secret, \ + const char *_labelPrefix, \ + unsigned int _labelPrefixLen, \ + SSLAeadContext **_ctx), \ + (version, cipherSuite, secret, \ + labelPrefix, labelPrefixLen, ctx)) + +#define SSL_AeadEncrypt(ctx, counter, aad, aadLen, in, inLen, \ + output, outputLen, maxOutputLen) \ + SSL_EXPERIMENTAL_API("SSL_AeadEncrypt", \ + (const SSLAeadContext *_ctx, PRUint64 _counter, \ + const PRUint8 *_aad, unsigned int _aadLen, \ + const PRUint8 *_in, unsigned int _inLen, \ + PRUint8 *_out, unsigned int *_outLen, \ + unsigned int _maxOut), \ + (ctx, counter, aad, aadLen, in, inLen, \ + output, outputLen, maxOutputLen)) + +#define SSL_AeadDecrypt(ctx, counter, aad, aadLen, in, inLen, \ + output, outputLen, maxOutputLen) \ + SSL_EXPERIMENTAL_API("SSL_AeadDecrypt", \ + (const SSLAeadContext *_ctx, PRUint64 _counter, \ + const PRUint8 *_aad, unsigned int _aadLen, \ + const PRUint8 *_in, unsigned int _inLen, \ + PRUint8 *_output, unsigned int *_outLen, \ + unsigned int _maxOut), \ + (ctx, counter, aad, aadLen, in, inLen, \ + output, outputLen, maxOutputLen)) + +#define SSL_DestroyAead(ctx) \ + SSL_EXPERIMENTAL_API("SSL_DestroyAead", \ + (SSLAeadContext * _ctx), \ + (ctx)) + +/* SSL_HkdfExtract and SSL_HkdfExpandLabel implement the functions from TLS, + * using the version and ciphersuite to set parameters. This allows callers to + * use these TLS functions as a KDF. This is only supported for TLS 1.3. + * + * SSL_HkdfExtract produces a key with a mechanism that is suitable for input to + * SSL_HkdfExpandLabel (and SSL_HkdfExpandLabelWithMech). */ +#define SSL_HkdfExtract(version, cipherSuite, salt, ikm, keyp) \ + SSL_EXPERIMENTAL_API("SSL_HkdfExtract", \ + (PRUint16 _version, PRUint16 _cipherSuite, \ + PK11SymKey * _salt, PK11SymKey * _ikm, \ + PK11SymKey * *_keyp), \ + (version, cipherSuite, salt, ikm, keyp)) + +/* SSL_HkdfExpandLabel produces a key with a mechanism that is suitable for + * input to SSL_HkdfExpandLabel or SSL_MakeAead. */ +#define SSL_HkdfExpandLabel(version, cipherSuite, prk, \ + hsHash, hsHashLen, label, labelLen, keyp) \ + SSL_EXPERIMENTAL_API("SSL_HkdfExpandLabel", \ + (PRUint16 _version, PRUint16 _cipherSuite, \ + PK11SymKey * _prk, \ + const PRUint8 *_hsHash, unsigned int _hsHashLen, \ + const char *_label, unsigned int _labelLen, \ + PK11SymKey **_keyp), \ + (version, cipherSuite, prk, \ + hsHash, hsHashLen, label, labelLen, keyp)) + +/* SSL_HkdfExpandLabelWithMech uses the KDF from the selected TLS version and + * cipher suite, as with the other calls, but the provided mechanism and key + * size. This allows the key to be used more widely. */ +#define SSL_HkdfExpandLabelWithMech(version, cipherSuite, prk, \ + hsHash, hsHashLen, label, labelLen, \ + mech, keySize, keyp) \ + SSL_EXPERIMENTAL_API("SSL_HkdfExpandLabelWithMech", \ + (PRUint16 _version, PRUint16 _cipherSuite, \ + PK11SymKey * _prk, \ + const PRUint8 *_hsHash, unsigned int _hsHashLen, \ + const char *_label, unsigned int _labelLen, \ + CK_MECHANISM_TYPE _mech, unsigned int _keySize, \ + PK11SymKey **_keyp), \ + (version, cipherSuite, prk, \ + hsHash, hsHashLen, label, labelLen, \ + mech, keySize, keyp)) + /* Deprecated experimental APIs */ #define SSL_UseAltServerHelloType(fd, enable) SSL_DEPRECATED_EXPERIMENTAL_API diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index 35240d2fba..575f4964a4 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -272,6 +272,7 @@ typedef struct sslOptionsStr { unsigned int enableDtlsShortHeader : 1; unsigned int enableHelloDowngradeCheck : 1; unsigned int enableV2CompatibleHello : 1; + unsigned int enablePostHandshakeAuth : 1; } sslOptions; typedef enum { sslHandshakingUndetermined = 0, @@ -622,8 +623,6 @@ typedef struct SSL3HandshakeStateStr { unsigned long msg_len; PRBool isResuming; /* we are resuming (not used in TLS 1.3) */ PRBool sendingSCSV; /* instead of empty RI */ - sslBuffer msgState; /* current state for handshake messages*/ - /* protected by recvBufLock */ /* The session ticket received in a NewSessionTicket message is temporarily * stored in newSessionTicket until the handshake is finished; then it is @@ -744,10 +743,10 @@ struct ssl3StateStr { * update is initiated locally. */ PRBool peerRequestedKeyUpdate; - /* Internal callback for when we do a cipher suite change. Used for - * debugging in TLS 1.3. This can only be set by non-public functions. */ - sslCipherSpecChangedFunc changedCipherSpecFunc; - void *changedCipherSpecArg; + /* This is true after the server requests client certificate; + * false after the client certificate is received. Used by the + * server. */ + PRBool clientCertRequested; CERTCertificate *clientCertificate; /* used by client */ SECKEYPrivateKey *clientPrivateKey; /* used by client */ @@ -994,6 +993,10 @@ struct sslSocketStr { PRCList extensionHooks; SSLResumptionTokenCallback resumptionTokenCallback; void *resumptionTokenContext; + SSLSecretCallback secretCallback; + void *secretCallbackArg; + SSLRecordWriteCallback recordWriteCallback; + void *recordWriteCallbackArg; PRIntervalTime rTimeout; /* timeout for NSPR I/O */ PRIntervalTime wTimeout; /* timeout for NSPR I/O */ @@ -1174,7 +1177,7 @@ extern SECStatus ssl_SaveWriteData(sslSocket *ss, const void *p, unsigned int l); extern SECStatus ssl_BeginClientHandshake(sslSocket *ss); extern SECStatus ssl_BeginServerHandshake(sslSocket *ss); -extern int ssl_Do1stHandshake(sslSocket *ss); +extern SECStatus ssl_Do1stHandshake(sslSocket *ss); extern SECStatus ssl3_InitPendingCipherSpecs(sslSocket *ss, PK11SymKey *secret, PRBool derive); @@ -1206,9 +1209,9 @@ extern SECStatus ssl_CipherPrefSetDefault(PRInt32 which, PRBool enabled); extern SECStatus ssl3_ConstrainRangeByPolicy(void); extern SECStatus ssl3_InitState(sslSocket *ss); -extern SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen, - int maxOutputLen, const unsigned char *input, - int inputLen); +extern SECStatus Null_Cipher(void *ctx, unsigned char *output, unsigned int *outputLen, + unsigned int maxOutputLen, const unsigned char *input, + unsigned int inputLen); extern void ssl3_RestartHandshakeHashes(sslSocket *ss); extern SECStatus ssl3_UpdateHandshakeHashes(sslSocket *ss, const unsigned char *b, @@ -1660,6 +1663,8 @@ SECStatus ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid, const ssl3CipherSuiteDef *ssl_LookupCipherSuiteDef(ssl3CipherSuite suite); const ssl3CipherSuiteCfg *ssl_LookupCipherSuiteCfg(ssl3CipherSuite suite, const ssl3CipherSuiteCfg *suites); +PRBool ssl3_CipherSuiteAllowedForVersionRange(ssl3CipherSuite cipherSuite, + const SSLVersionRange *vrange); SECStatus ssl3_SelectServerCert(sslSocket *ss); SECStatus ssl_PickSignatureScheme(sslSocket *ss, @@ -1729,6 +1734,14 @@ SECStatus ssl_DecodeResumptionToken(sslSessionID *sid, const PRUint8 *encodedTic PRUint32 encodedTicketLen); PRBool ssl_IsResumptionTokenUsable(sslSocket *ss, sslSessionID *sid); +/* unwrap helper function to handle the case where the wrapKey doesn't wind + * * up in the correct token for the master secret */ +PK11SymKey *ssl_unwrapSymKey(PK11SymKey *wrapKey, + CK_MECHANISM_TYPE wrapType, SECItem *param, + SECItem *wrappedKey, + CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, + int keySize, CK_FLAGS keyFlags, void *pinArg); + /* Remove when stable. */ SECStatus SSLExp_SetResumptionTokenCallback(PRFileDesc *fd, @@ -1742,8 +1755,45 @@ SECStatus SSLExp_GetResumptionTokenInfo(const PRUint8 *tokenData, unsigned int t SECStatus SSLExp_DestroyResumptionTokenInfo(SSLResumptionTokenInfo *token); +SECStatus SSLExp_SecretCallback(PRFileDesc *fd, SSLSecretCallback cb, + void *arg); +SECStatus SSLExp_RecordLayerWriteCallback(PRFileDesc *fd, + SSLRecordWriteCallback write, + void *arg); +SECStatus SSLExp_RecordLayerData(PRFileDesc *fd, PRUint16 epoch, + SSLContentType contentType, + const PRUint8 *data, unsigned int len); +SECStatus SSLExp_GetCurrentEpoch(PRFileDesc *fd, PRUint16 *readEpoch, + PRUint16 *writeEpoch); + #define SSLResumptionTokenVersion 2 +SECStatus SSLExp_MakeAead(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *secret, + const char *labelPrefix, unsigned int labelPrefixLen, + SSLAeadContext **ctx); +SECStatus SSLExp_DestroyAead(SSLAeadContext *ctx); +SECStatus SSLExp_AeadEncrypt(const SSLAeadContext *ctx, PRUint64 counter, + const PRUint8 *aad, unsigned int aadLen, + const PRUint8 *plaintext, unsigned int plaintextLen, + PRUint8 *out, unsigned int *outLen, unsigned int maxOut); +SECStatus SSLExp_AeadDecrypt(const SSLAeadContext *ctx, PRUint64 counter, + const PRUint8 *aad, unsigned int aadLen, + const PRUint8 *plaintext, unsigned int plaintextLen, + PRUint8 *out, unsigned int *outLen, unsigned int maxOut); + +SECStatus SSLExp_HkdfExtract(PRUint16 version, PRUint16 cipherSuite, + PK11SymKey *salt, PK11SymKey *ikm, PK11SymKey **keyp); +SECStatus SSLExp_HkdfExpandLabel(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *prk, + const PRUint8 *hsHash, unsigned int hsHashLen, + const char *label, unsigned int labelLen, + PK11SymKey **key); +SECStatus +SSLExp_HkdfExpandLabelWithMech(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *prk, + const PRUint8 *hsHash, unsigned int hsHashLen, + const char *label, unsigned int labelLen, + CK_MECHANISM_TYPE mech, unsigned int keySize, + PK11SymKey **keyp); + SEC_END_PROTOS #if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS) diff --git a/security/nss/lib/ssl/sslinfo.c b/security/nss/lib/ssl/sslinfo.c index 4e58c5ae7c..9eb22f0811 100644 --- a/security/nss/lib/ssl/sslinfo.c +++ b/security/nss/lib/ssl/sslinfo.c @@ -150,6 +150,7 @@ SSL_GetPreliminaryChannelInfo(PRFileDesc *fd, } else { inf.maxEarlyDataSize = 0; } + inf.zeroRttCipherSuite = ss->ssl3.hs.zeroRttSuite; memcpy(info, &inf, inf.length); return SECSuccess; @@ -234,89 +235,89 @@ SSL_GetPreliminaryChannelInfo(PRFileDesc *fd, static const SSLCipherSuiteInfo suiteInfo[] = { /* <------ Cipher suite --------------------> */ - { 0, CS_(TLS_AES_128_GCM_SHA256), S_ANY, K_ANY, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_ANY }, - { 0, CS_(TLS_CHACHA20_POLY1305_SHA256), S_ANY, K_ANY, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_ANY }, - { 0, CS_(TLS_AES_256_GCM_SHA384), S_ANY, K_ANY, C_AESGCM, B_256, M_AEAD_128, F_NFIPS_STD, A_ANY }, + { 0, CS_(TLS_AES_128_GCM_SHA256), S_ANY, K_ANY, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_ANY, ssl_hash_sha256 }, + { 0, CS_(TLS_CHACHA20_POLY1305_SHA256), S_ANY, K_ANY, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_ANY, ssl_hash_sha256 }, + { 0, CS_(TLS_AES_256_GCM_SHA384), S_ANY, K_ANY, C_AESGCM, B_256, M_AEAD_128, F_NFIPS_STD, A_ANY, ssl_hash_sha384 }, - { 0, CS(RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_RSA, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAD }, - { 0, CS(DHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_DHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_RSAS }, + { 0, CS(RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_RSA, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAD, ssl_hash_sha256 }, + { 0, CS(DHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_DHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_RSAS, ssl_hash_sha256 }, - { 0, CS(DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_RSAS }, - { 0, CS(DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_DSA }, - { 0, CS(DHE_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_DHE, C_AES, B_256, M_SHA256, F_FIPS_STD, A_RSAS }, - { 0, CS(DHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_DHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAS }, - { 0, CS(DHE_DSS_WITH_AES_256_CBC_SHA), S_DSA, K_DHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_DSA }, - { 0, CS(DHE_DSS_WITH_AES_256_CBC_SHA256), S_DSA, K_DHE, C_AES, B_256, M_SHA256, F_FIPS_STD, A_DSA }, - { 0, CS(RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_RSAD }, - { 0, CS(RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_RSA, C_AES, B_256, M_SHA256, F_FIPS_STD, A_RSAD }, - { 0, CS(RSA_WITH_AES_256_CBC_SHA), S_RSA, K_RSA, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAD }, + { 0, CS(DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_RSAS, ssl_hash_none }, + { 0, CS(DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_DSA, ssl_hash_none }, + { 0, CS(DHE_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_DHE, C_AES, B_256, M_SHA256, F_FIPS_STD, A_RSAS, ssl_hash_sha256 }, + { 0, CS(DHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_DHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAS, ssl_hash_none }, + { 0, CS(DHE_DSS_WITH_AES_256_CBC_SHA), S_DSA, K_DHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_DSA, ssl_hash_none }, + { 0, CS(DHE_DSS_WITH_AES_256_CBC_SHA256), S_DSA, K_DHE, C_AES, B_256, M_SHA256, F_FIPS_STD, A_DSA, ssl_hash_sha256 }, + { 0, CS(RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_RSAD, ssl_hash_none }, + { 0, CS(RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_RSA, C_AES, B_256, M_SHA256, F_FIPS_STD, A_RSAD, ssl_hash_sha256 }, + { 0, CS(RSA_WITH_AES_256_CBC_SHA), S_RSA, K_RSA, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAD, ssl_hash_none }, - { 0, CS(DHE_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_RSAS }, - { 0, CS(DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_DSA }, - { 0, CS(DHE_DSS_WITH_RC4_128_SHA), S_DSA, K_DHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_DSA }, - { 0, CS(DHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_DHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAS }, - { 0, CS(DHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAS }, - { 0, CS(DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAS }, - { 0, CS(DHE_DSS_WITH_AES_128_GCM_SHA256), S_DSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_DSA }, - { 0, CS(DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_DSA }, - { 0, CS(DHE_DSS_WITH_AES_128_CBC_SHA256), S_DSA, K_DHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_DSA }, - { 0, CS(RSA_WITH_SEED_CBC_SHA), S_RSA, K_RSA, C_SEED, B_128, M_SHA, F_FIPS_STD, A_RSAD }, - { 0, CS(RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_RSAD }, - { 0, CS(RSA_WITH_RC4_128_SHA), S_RSA, K_RSA, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_RSAD }, - { 0, CS(RSA_WITH_RC4_128_MD5), S_RSA, K_RSA, C_RC4, B_128, M_MD5, F_NFIPS_STD, A_RSAD }, - { 0, CS(RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_RSA, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAD }, - { 0, CS(RSA_WITH_AES_128_CBC_SHA), S_RSA, K_RSA, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAD }, + { 0, CS(DHE_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_RSAS, ssl_hash_none }, + { 0, CS(DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_DSA, ssl_hash_none }, + { 0, CS(DHE_DSS_WITH_RC4_128_SHA), S_DSA, K_DHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_DSA, ssl_hash_none }, + { 0, CS(DHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_DHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAS, ssl_hash_sha256 }, + { 0, CS(DHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAS, ssl_hash_sha256 }, + { 0, CS(DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAS, ssl_hash_none }, + { 0, CS(DHE_DSS_WITH_AES_128_GCM_SHA256), S_DSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_DSA, ssl_hash_sha256 }, + { 0, CS(DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_DSA, ssl_hash_none }, + { 0, CS(DHE_DSS_WITH_AES_128_CBC_SHA256), S_DSA, K_DHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_DSA, ssl_hash_sha256 }, + { 0, CS(RSA_WITH_SEED_CBC_SHA), S_RSA, K_RSA, C_SEED, B_128, M_SHA, F_FIPS_STD, A_RSAD, ssl_hash_none }, + { 0, CS(RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_RSAD, ssl_hash_none }, + { 0, CS(RSA_WITH_RC4_128_SHA), S_RSA, K_RSA, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_RSAD, ssl_hash_none }, + { 0, CS(RSA_WITH_RC4_128_MD5), S_RSA, K_RSA, C_RC4, B_128, M_MD5, F_NFIPS_STD, A_RSAD, ssl_hash_none }, + { 0, CS(RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_RSA, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAD, ssl_hash_sha256 }, + { 0, CS(RSA_WITH_AES_128_CBC_SHA), S_RSA, K_RSA, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAD, ssl_hash_none }, - { 0, CS(DHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_DHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAS }, - { 0, CS(DHE_DSS_WITH_3DES_EDE_CBC_SHA), S_DSA, K_DHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_DSA }, - { 0, CS(RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAD }, + { 0, CS(DHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_DHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAS, ssl_hash_none }, + { 0, CS(DHE_DSS_WITH_3DES_EDE_CBC_SHA), S_DSA, K_DHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_DSA, ssl_hash_none }, + { 0, CS(RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAD, ssl_hash_none }, - { 0, CS(DHE_RSA_WITH_DES_CBC_SHA), S_RSA, K_DHE, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_RSAS }, - { 0, CS(DHE_DSS_WITH_DES_CBC_SHA), S_DSA, K_DHE, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_DSA }, - { 0, CS(RSA_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_RSAD }, + { 0, CS(DHE_RSA_WITH_DES_CBC_SHA), S_RSA, K_DHE, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_RSAS, ssl_hash_none }, + { 0, CS(DHE_DSS_WITH_DES_CBC_SHA), S_DSA, K_DHE, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_DSA, ssl_hash_none }, + { 0, CS(RSA_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_RSAD, ssl_hash_none }, - { 0, CS(RSA_WITH_NULL_SHA256), S_RSA, K_RSA, C_NULL, B_0, M_SHA256, F_EXPORT, A_RSAD }, - { 0, CS(RSA_WITH_NULL_SHA), S_RSA, K_RSA, C_NULL, B_0, M_SHA, F_EXPORT, A_RSAD }, - { 0, CS(RSA_WITH_NULL_MD5), S_RSA, K_RSA, C_NULL, B_0, M_MD5, F_EXPORT, A_RSAD }, + { 0, CS(RSA_WITH_NULL_SHA256), S_RSA, K_RSA, C_NULL, B_0, M_SHA256, F_EXPORT, A_RSAD, ssl_hash_sha256 }, + { 0, CS(RSA_WITH_NULL_SHA), S_RSA, K_RSA, C_NULL, B_0, M_SHA, F_EXPORT, A_RSAD, ssl_hash_none }, + { 0, CS(RSA_WITH_NULL_MD5), S_RSA, K_RSA, C_NULL, B_0, M_MD5, F_EXPORT, A_RSAD, ssl_hash_none }, /* ECC cipher suites */ - { 0, CS(ECDHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAS }, - { 0, CS(ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), S_ECDSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_ECDSA }, - { 0, CS(ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDH_E }, - { 0, CS(ECDH_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDH_E }, - { 0, CS(ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDH_E }, - { 0, CS(ECDH_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDH_E }, - { 0, CS(ECDH_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDH_E }, + { 0, CS(ECDHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAS, ssl_hash_sha256 }, + { 0, CS(ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), S_ECDSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_ECDSA, ssl_hash_sha256 }, + { 0, CS(ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDH_E, ssl_hash_none }, + { 0, CS(ECDH_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDH_E, ssl_hash_none }, + { 0, CS(ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDH_E, ssl_hash_none }, + { 0, CS(ECDH_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDH_E, ssl_hash_none }, + { 0, CS(ECDH_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDH_E, ssl_hash_none }, - { 0, CS(ECDHE_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDHE, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_ECDSA_WITH_AES_128_CBC_SHA256), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), S_ECDSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_ECDSA }, + { 0, CS(ECDHE_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDHE, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDSA, ssl_hash_none }, + { 0, CS(ECDHE_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDSA, ssl_hash_none }, + { 0, CS(ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDSA, ssl_hash_none }, + { 0, CS(ECDHE_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDSA, ssl_hash_none }, + { 0, CS(ECDHE_ECDSA_WITH_AES_128_CBC_SHA256), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_ECDSA, ssl_hash_sha256 }, + { 0, CS(ECDHE_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDSA, ssl_hash_none }, + { 0, CS(ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), S_ECDSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_ECDSA, ssl_hash_sha256 }, - { 0, CS(ECDH_RSA_WITH_NULL_SHA), S_RSA, K_ECDH, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDH_R }, - { 0, CS(ECDH_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDH, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDH_R }, - { 0, CS(ECDH_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDH, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDH_R }, - { 0, CS(ECDH_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDH, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDH_R }, - { 0, CS(ECDH_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDH, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDH_R }, + { 0, CS(ECDH_RSA_WITH_NULL_SHA), S_RSA, K_ECDH, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDH_R, ssl_hash_none }, + { 0, CS(ECDH_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDH, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDH_R, ssl_hash_none }, + { 0, CS(ECDH_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDH, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDH_R, ssl_hash_none }, + { 0, CS(ECDH_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDH, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDH_R, ssl_hash_none }, + { 0, CS(ECDH_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDH, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDH_R, ssl_hash_none }, - { 0, CS(ECDHE_RSA_WITH_NULL_SHA), S_RSA, K_ECDHE, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_RSAS }, - { 0, CS(ECDHE_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_RSAS }, - { 0, CS(ECDHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAS }, - { 0, CS(ECDHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAS }, - { 0, CS(ECDHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_ECDHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAS }, - { 0, CS(ECDHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAS }, - { 0, CS(ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_RSAS }, - { 0, CS(ECDHE_RSA_WITH_AES_256_CBC_SHA384), S_RSA, K_ECDHE, C_AES, B_256, M_SHA384, F_FIPS_STD, A_RSAS }, - { 0, CS(ECDHE_ECDSA_WITH_AES_256_CBC_SHA384), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA384, F_FIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), S_ECDSA, K_ECDHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_ECDHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAS }, + { 0, CS(ECDHE_RSA_WITH_NULL_SHA), S_RSA, K_ECDHE, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_RSAS, ssl_hash_none }, + { 0, CS(ECDHE_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_RSAS, ssl_hash_none }, + { 0, CS(ECDHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAS, ssl_hash_none }, + { 0, CS(ECDHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAS, ssl_hash_none }, + { 0, CS(ECDHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_ECDHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAS, ssl_hash_sha256 }, + { 0, CS(ECDHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAS, ssl_hash_none }, + { 0, CS(ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_RSAS, ssl_hash_sha256 }, + { 0, CS(ECDHE_RSA_WITH_AES_256_CBC_SHA384), S_RSA, K_ECDHE, C_AES, B_256, M_SHA384, F_FIPS_STD, A_RSAS, ssl_hash_sha384 }, + { 0, CS(ECDHE_ECDSA_WITH_AES_256_CBC_SHA384), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA384, F_FIPS_STD, A_ECDSA, ssl_hash_sha384 }, + { 0, CS(ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), S_ECDSA, K_ECDHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_ECDSA, ssl_hash_sha384 }, + { 0, CS(ECDHE_RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_ECDHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAS, ssl_hash_sha384 }, - { 0, CS(DHE_DSS_WITH_AES_256_GCM_SHA384), S_DSA, K_DHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_DSA }, - { 0, CS(DHE_RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_DHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAS }, - { 0, CS(RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_RSA, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAD }, + { 0, CS(DHE_DSS_WITH_AES_256_GCM_SHA384), S_DSA, K_DHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_DSA, ssl_hash_sha384 }, + { 0, CS(DHE_RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_DHE, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAS, ssl_hash_sha384 }, + { 0, CS(RSA_WITH_AES_256_GCM_SHA384), S_RSA, K_RSA, C_AESGCM, B_256, M_AEAD_128, F_FIPS_STD, A_RSAD, ssl_hash_sha384 }, }; #define NUM_SUITEINFOS ((sizeof suiteInfo) / (sizeof suiteInfo[0])) diff --git a/security/nss/lib/ssl/sslprimitive.c b/security/nss/lib/ssl/sslprimitive.c new file mode 100644 index 0000000000..540c178400 --- /dev/null +++ b/security/nss/lib/ssl/sslprimitive.c @@ -0,0 +1,274 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * SSL Primitives: Public HKDF and AEAD Functions + * + * 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/. */ + +#include "keyhi.h" +#include "pk11pub.h" +#include "sechash.h" +#include "ssl.h" +#include "sslexp.h" +#include "sslerr.h" +#include "sslproto.h" + +#include "sslimpl.h" +#include "tls13con.h" +#include "tls13hkdf.h" + +struct SSLAeadContextStr { + CK_MECHANISM_TYPE mech; + ssl3KeyMaterial keys; +}; + +static SECStatus +tls13_GetHashAndCipher(PRUint16 version, PRUint16 cipherSuite, + SSLHashType *hash, const ssl3BulkCipherDef **cipher) +{ + if (version < SSL_LIBRARY_VERSION_TLS_1_3) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + // Lookup and check the suite. + SSLVersionRange vrange = { version, version }; + if (!ssl3_CipherSuiteAllowedForVersionRange(cipherSuite, &vrange)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + const ssl3CipherSuiteDef *suiteDef = ssl_LookupCipherSuiteDef(cipherSuite); + const ssl3BulkCipherDef *cipherDef = ssl_GetBulkCipherDef(suiteDef); + if (cipherDef->type != type_aead) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + *hash = suiteDef->prf_hash; + if (cipher != NULL) { + *cipher = cipherDef; + } + return SECSuccess; +} + +SECStatus +SSLExp_MakeAead(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *secret, + const char *labelPrefix, unsigned int labelPrefixLen, + SSLAeadContext **ctx) +{ + SSLAeadContext *out = NULL; + char label[255]; // Maximum length label. + static const char *const keySuffix = "key"; + static const char *const ivSuffix = "iv"; + + PORT_Assert(strlen(keySuffix) >= strlen(ivSuffix)); + if (secret == NULL || ctx == NULL || + (labelPrefix == NULL && labelPrefixLen > 0) || + labelPrefixLen + strlen(keySuffix) > sizeof(label)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto loser; + } + + SSLHashType hash; + const ssl3BulkCipherDef *cipher; + SECStatus rv = tls13_GetHashAndCipher(version, cipherSuite, + &hash, &cipher); + if (rv != SECSuccess) { + goto loser; /* Code already set. */ + } + + out = PORT_ZNew(SSLAeadContext); + if (out == NULL) { + goto loser; + } + out->mech = ssl3_Alg2Mech(cipher->calg); + + memcpy(label, labelPrefix, labelPrefixLen); + memcpy(label + labelPrefixLen, ivSuffix, strlen(ivSuffix)); + unsigned int labelLen = labelPrefixLen + strlen(ivSuffix); + unsigned int ivLen = cipher->iv_size + cipher->explicit_nonce_size; + rv = tls13_HkdfExpandLabelRaw(secret, hash, + NULL, 0, // Handshake hash. + label, labelLen, + out->keys.iv, ivLen); + if (rv != SECSuccess) { + goto loser; + } + + memcpy(label + labelPrefixLen, keySuffix, strlen(keySuffix)); + labelLen = labelPrefixLen + strlen(keySuffix); + rv = tls13_HkdfExpandLabel(secret, hash, + NULL, 0, // Handshake hash. + label, labelLen, + out->mech, cipher->key_size, &out->keys.key); + if (rv != SECSuccess) { + goto loser; + } + + *ctx = out; + return SECSuccess; + +loser: + SSLExp_DestroyAead(out); + return SECFailure; +} + +SECStatus +SSLExp_DestroyAead(SSLAeadContext *ctx) +{ + if (!ctx) { + return SECSuccess; + } + + PK11_FreeSymKey(ctx->keys.key); + PORT_ZFree(ctx, sizeof(*ctx)); + return SECSuccess; +} + +/* Bug 1529440 exists to refactor this and the other AEAD uses. */ +static SECStatus +ssl_AeadInner(const SSLAeadContext *ctx, PRBool decrypt, PRUint64 counter, + const PRUint8 *aad, unsigned int aadLen, + const PRUint8 *plaintext, unsigned int plaintextLen, + PRUint8 *out, unsigned int *outLen, unsigned int maxOut) +{ + if (ctx == NULL || (aad == NULL && aadLen > 0) || plaintext == NULL || + out == NULL || outLen == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + // Setup the nonce. + PRUint8 nonce[12] = { 0 }; + sslBuffer nonceBuf = SSL_BUFFER_FIXED(nonce + sizeof(nonce) - sizeof(counter), + sizeof(counter)); + SECStatus rv = sslBuffer_AppendNumber(&nonceBuf, counter, sizeof(counter)); + if (rv != SECSuccess) { + PORT_Assert(0); + return SECFailure; + } + for (int i = 0; i < sizeof(nonce); ++i) { + nonce[i] ^= ctx->keys.iv[i]; + } + + // Build AEAD parameters. + CK_GCM_PARAMS gcmParams = { 0 }; + CK_NSS_AEAD_PARAMS aeadParams = { 0 }; + unsigned char *params; + unsigned int paramsLen; + switch (ctx->mech) { + case CKM_AES_GCM: + gcmParams.pIv = nonce; + gcmParams.ulIvLen = sizeof(nonce); + gcmParams.pAAD = (unsigned char *)aad; // const cast :( + gcmParams.ulAADLen = aadLen; + gcmParams.ulTagBits = 128; // GCM measures in bits. + params = (unsigned char *)&gcmParams; + paramsLen = sizeof(gcmParams); + break; + + case CKM_NSS_CHACHA20_POLY1305: + aeadParams.pNonce = nonce; + aeadParams.ulNonceLen = sizeof(nonce); + aeadParams.pAAD = (unsigned char *)aad; // const cast :( + aeadParams.ulAADLen = aadLen; + aeadParams.ulTagLen = 16; // AEAD measures in octets. + params = (unsigned char *)&aeadParams; + paramsLen = sizeof(aeadParams); + break; + + default: + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + return tls13_AEAD(&ctx->keys, decrypt, out, outLen, maxOut, + plaintext, plaintextLen, ctx->mech, params, paramsLen); +} + +SECStatus +SSLExp_AeadEncrypt(const SSLAeadContext *ctx, PRUint64 counter, + const PRUint8 *aad, unsigned int aadLen, + const PRUint8 *plaintext, unsigned int plaintextLen, + PRUint8 *out, unsigned int *outLen, unsigned int maxOut) +{ + // false == encrypt + return ssl_AeadInner(ctx, PR_FALSE, counter, aad, aadLen, + plaintext, plaintextLen, out, outLen, maxOut); +} + +SECStatus +SSLExp_AeadDecrypt(const SSLAeadContext *ctx, PRUint64 counter, + const PRUint8 *aad, unsigned int aadLen, + const PRUint8 *plaintext, unsigned int plaintextLen, + PRUint8 *out, unsigned int *outLen, unsigned int maxOut) +{ + // true == decrypt + return ssl_AeadInner(ctx, PR_TRUE, counter, aad, aadLen, + plaintext, plaintextLen, out, outLen, maxOut); +} + +SECStatus +SSLExp_HkdfExtract(PRUint16 version, PRUint16 cipherSuite, + PK11SymKey *salt, PK11SymKey *ikm, PK11SymKey **keyp) +{ + if (keyp == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + SSLHashType hash; + SECStatus rv = tls13_GetHashAndCipher(version, cipherSuite, + &hash, NULL); + if (rv != SECSuccess) { + return SECFailure; /* Code already set. */ + } + return tls13_HkdfExtract(salt, ikm, hash, keyp); +} + +SECStatus +SSLExp_HkdfExpandLabel(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *prk, + const PRUint8 *hsHash, unsigned int hsHashLen, + const char *label, unsigned int labelLen, + PK11SymKey **keyp) +{ + if (prk == NULL || keyp == NULL || + label == NULL || labelLen == 0) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + SSLHashType hash; + SECStatus rv = tls13_GetHashAndCipher(version, cipherSuite, + &hash, NULL); + if (rv != SECSuccess) { + return SECFailure; /* Code already set. */ + } + return tls13_HkdfExpandLabel(prk, hash, hsHash, hsHashLen, label, labelLen, + tls13_GetHkdfMechanismForHash(hash), + tls13_GetHashSizeForHash(hash), keyp); +} + +SECStatus +SSLExp_HkdfExpandLabelWithMech(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *prk, + const PRUint8 *hsHash, unsigned int hsHashLen, + const char *label, unsigned int labelLen, + CK_MECHANISM_TYPE mech, unsigned int keySize, + PK11SymKey **keyp) +{ + if (prk == NULL || keyp == NULL || + label == NULL || labelLen == 0 || + mech == CKM_INVALID_MECHANISM || keySize == 0) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + SSLHashType hash; + SECStatus rv = tls13_GetHashAndCipher(version, cipherSuite, + &hash, NULL); + if (rv != SECSuccess) { + return SECFailure; /* Code already set. */ + } + return tls13_HkdfExpandLabel(prk, hash, hsHash, hsHashLen, label, labelLen, + mech, keySize, keyp); +} diff --git a/security/nss/lib/ssl/sslsecur.c b/security/nss/lib/ssl/sslsecur.c index c011b66a11..79634e4039 100644 --- a/security/nss/lib/ssl/sslsecur.c +++ b/security/nss/lib/ssl/sslsecur.c @@ -16,32 +16,7 @@ #include "nss.h" /* for NSS_RegisterShutdown */ #include "prinit.h" /* for PR_CallOnceWithArg */ -/* Returns a SECStatus: SECSuccess or SECFailure, NOT SECWouldBlock. - * - * Currently, the list of functions called through ss->handshake is: - * - * In sslsocks.c: - * SocksGatherRecord - * SocksHandleReply - * SocksStartGather - * - * In sslcon.c: - * ssl_GatherRecord1stHandshake - * ssl_BeginClientHandshake - * ssl_BeginServerHandshake - * - * The ss->handshake function returns SECWouldBlock if it was returned by - * one of the callback functions, via one of these paths: - * - * - ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() -> - * ssl3_HandleRecord() -> ssl3_HandleHandshake() -> - * ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificate() -> - * ss->handleBadCert() - * - * - ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() -> - * ssl3_HandleRecord() -> ssl3_HandleHandshake() -> - * ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificateRequest() -> - * ss->getClientAuthData() +/* Step through the handshake functions. * * Called from: SSL_ForceHandshake (below), * ssl_SecureRecv (below) and @@ -52,10 +27,10 @@ * * Caller must hold the (write) handshakeLock. */ -int +SECStatus ssl_Do1stHandshake(sslSocket *ss) { - int rv = SECSuccess; + SECStatus rv = SECSuccess; while (ss->handshake && rv == SECSuccess) { PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss)); @@ -70,10 +45,6 @@ ssl_Do1stHandshake(sslSocket *ss) PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss)); PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss)); - if (rv == SECWouldBlock) { - PORT_SetError(PR_WOULD_BLOCK_ERROR); - rv = SECFailure; - } return rv; } @@ -106,8 +77,8 @@ ssl_FinishHandshake(sslSocket *ss) static SECStatus ssl3_AlwaysBlock(sslSocket *ss) { - PORT_SetError(PR_WOULD_BLOCK_ERROR); /* perhaps redundant. */ - return SECWouldBlock; + PORT_SetError(PR_WOULD_BLOCK_ERROR); + return SECFailure; } /* @@ -400,10 +371,13 @@ SSL_ForceHandshake(PRFileDesc *fd) ssl_ReleaseRecvBufLock(ss); if (gatherResult > 0) { rv = SECSuccess; - } else if (gatherResult == 0) { - PORT_SetError(PR_END_OF_FILE_ERROR); - } else if (gatherResult == SECWouldBlock) { - PORT_SetError(PR_WOULD_BLOCK_ERROR); + } else { + if (gatherResult == 0) { + PORT_SetError(PR_END_OF_FILE_ERROR); + } + /* We can rely on ssl3_GatherCompleteHandshake to set + * PR_WOULD_BLOCK_ERROR as needed here. */ + rv = SECFailure; } } else { PORT_Assert(!ss->firstHsDone); @@ -515,8 +489,7 @@ DoRecv(sslSocket *ss, unsigned char *out, int len, int flags) SSL_GETPID(), ss->fd)); goto done; } - if ((rv != SECWouldBlock) && - (PR_GetError() != PR_WOULD_BLOCK_ERROR)) { + if (PR_GetError() != PR_WOULD_BLOCK_ERROR) { /* Some random error */ goto done; } @@ -741,7 +714,7 @@ ssl_SecureShutdown(sslSocket *ss, int nsprHow) /************************************************************************/ static SECStatus -tls13_CheckKeyUpdate(sslSocket *ss, CipherSpecDirection dir) +tls13_CheckKeyUpdate(sslSocket *ss, SSLSecretDirection dir) { PRBool keyUpdate; ssl3CipherSpec *spec; @@ -765,7 +738,7 @@ tls13_CheckKeyUpdate(sslSocket *ss, CipherSpecDirection dir) * having the write margin larger reduces the number of times that a * KeyUpdate is sent by a reader. */ ssl_GetSpecReadLock(ss); - if (dir == CipherSpecRead) { + if (dir == ssl_secret_read) { spec = ss->ssl3.crSpec; margin = spec->cipherDef->max_records / 8; } else { @@ -781,10 +754,10 @@ tls13_CheckKeyUpdate(sslSocket *ss, CipherSpecDirection dir) SSL_TRC(5, ("%d: SSL[%d]: automatic key update at %llx for %s cipher spec", SSL_GETPID(), ss->fd, seqNum, - (dir == CipherSpecRead) ? "read" : "write")); + (dir == ssl_secret_read) ? "read" : "write")); ssl_GetSSL3HandshakeLock(ss); - rv = tls13_SendKeyUpdate(ss, (dir == CipherSpecRead) ? update_requested : update_not_requested, - dir == CipherSpecWrite /* buffer */); + rv = tls13_SendKeyUpdate(ss, (dir == ssl_secret_read) ? update_requested : update_not_requested, + dir == ssl_secret_write /* buffer */); ssl_ReleaseSSL3HandshakeLock(ss); return rv; } @@ -829,7 +802,7 @@ ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags) } ssl_Release1stHandshakeLock(ss); } else { - if (tls13_CheckKeyUpdate(ss, CipherSpecRead) != SECSuccess) { + if (tls13_CheckKeyUpdate(ss, ssl_secret_read) != SECSuccess) { rv = PR_FAILURE; } } @@ -955,7 +928,7 @@ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags) } if (ss->firstHsDone) { - if (tls13_CheckKeyUpdate(ss, CipherSpecWrite) != SECSuccess) { + if (tls13_CheckKeyUpdate(ss, ssl_secret_write) != SECSuccess) { rv = PR_FAILURE; goto done; } @@ -1010,6 +983,35 @@ ssl_SecureWrite(sslSocket *ss, const unsigned char *buf, int len) return ssl_SecureSend(ss, buf, len, 0); } +SECStatus +SSLExp_RecordLayerWriteCallback(PRFileDesc *fd, SSLRecordWriteCallback cb, + void *arg) +{ + sslSocket *ss = ssl_FindSocket(fd); + if (!ss) { + SSL_DBG(("%d: SSL[%d]: invalid socket for SSL_RecordLayerWriteCallback", + SSL_GETPID(), fd)); + return SECFailure; + } + if (IS_DTLS(ss)) { + SSL_DBG(("%d: SSL[%d]: DTLS socket for SSL_RecordLayerWriteCallback", + SSL_GETPID(), fd)); + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + /* This needs both HS and Xmit locks because this value is checked under + * both locks. HS to disable reading from the underlying IO layer; Xmit to + * prevent writing. */ + ssl_GetSSL3HandshakeLock(ss); + ssl_GetXmitBufLock(ss); + ss->recordWriteCallback = cb; + ss->recordWriteCallbackArg = arg; + ssl_ReleaseXmitBufLock(ss); + ssl_ReleaseSSL3HandshakeLock(ss); + return SECSuccess; +} + SECStatus SSL_AlertReceivedCallback(PRFileDesc *fd, SSLAlertCallback cb, void *arg) { diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c index 00855be004..96b963bc26 100644 --- a/security/nss/lib/ssl/sslsock.c +++ b/security/nss/lib/ssl/sslsock.c @@ -86,7 +86,8 @@ static sslOptions ssl_defaults = { .enableTls13CompatMode = PR_FALSE, .enableDtlsShortHeader = PR_FALSE, .enableHelloDowngradeCheck = PR_FALSE, - .enableV2CompatibleHello = PR_FALSE + .enableV2CompatibleHello = PR_FALSE, + .enablePostHandshakeAuth = PR_FALSE }; /* @@ -842,6 +843,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRIntn val) ss->opt.enableV2CompatibleHello = val; break; + case SSL_ENABLE_POST_HANDSHAKE_AUTH: + ss->opt.enablePostHandshakeAuth = val; + break; + default: PORT_SetError(SEC_ERROR_INVALID_ARGS); rv = SECFailure; @@ -990,6 +995,9 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRIntn *pVal) case SSL_ENABLE_V2_COMPATIBLE_HELLO: val = ss->opt.enableV2CompatibleHello; break; + case SSL_ENABLE_POST_HANDSHAKE_AUTH: + val = ss->opt.enablePostHandshakeAuth; + break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); rv = SECFailure; @@ -1122,6 +1130,9 @@ SSL_OptionGetDefault(PRInt32 which, PRIntn *pVal) case SSL_ENABLE_V2_COMPATIBLE_HELLO: val = ssl_defaults.enableV2CompatibleHello; break; + case SSL_ENABLE_POST_HANDSHAKE_AUTH: + val = ssl_defaults.enablePostHandshakeAuth; + break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); rv = SECFailure; @@ -1325,6 +1336,10 @@ SSL_OptionSetDefault(PRInt32 which, PRIntn val) ssl_defaults.enableV2CompatibleHello = val; break; + case SSL_ENABLE_POST_HANDSHAKE_AUTH: + ssl_defaults.enablePostHandshakeAuth = val; + break; + default: PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; @@ -4026,20 +4041,32 @@ struct { void *function; } ssl_experimental_functions[] = { #ifndef SSL_DISABLE_EXPERIMENTAL_API + EXP(AeadDecrypt), + EXP(AeadEncrypt), + EXP(DestroyAead), + EXP(DestroyResumptionTokenInfo), + EXP(EnableESNI), + EXP(EncodeESNIKeys), + EXP(GetCurrentEpoch), EXP(GetExtensionSupport), + EXP(GetResumptionTokenInfo), EXP(HelloRetryRequestCallback), EXP(InstallExtensionHooks), + EXP(HkdfExtract), + EXP(HkdfExpandLabel), + EXP(HkdfExpandLabelWithMech), EXP(KeyUpdate), + EXP(MakeAead), + EXP(RecordLayerData), + EXP(RecordLayerWriteCallback), + EXP(SecretCallback), + EXP(SendCertificateRequest), EXP(SendSessionTicket), + EXP(SetESNIKeyPair), EXP(SetMaxEarlyDataSize), - EXP(SetupAntiReplay), EXP(SetResumptionTokenCallback), EXP(SetResumptionToken), - EXP(GetResumptionTokenInfo), - EXP(DestroyResumptionTokenInfo), - EXP(SetESNIKeyPair), - EXP(EncodeESNIKeys), - EXP(EnableESNI), + EXP(SetupAntiReplay), #endif { "", NULL } }; diff --git a/security/nss/lib/ssl/sslspec.c b/security/nss/lib/ssl/sslspec.c index f2e72a4ec4..def3c67505 100644 --- a/security/nss/lib/ssl/sslspec.c +++ b/security/nss/lib/ssl/sslspec.c @@ -113,7 +113,7 @@ ssl_GetMacDef(const sslSocket *ss, const ssl3CipherSuiteDef *suiteDef) } ssl3CipherSpec * -ssl_FindCipherSpecByEpoch(sslSocket *ss, CipherSpecDirection direction, +ssl_FindCipherSpecByEpoch(sslSocket *ss, SSLSecretDirection direction, DTLSEpoch epoch) { PRCList *cur_p; @@ -134,7 +134,7 @@ ssl_FindCipherSpecByEpoch(sslSocket *ss, CipherSpecDirection direction, } ssl3CipherSpec * -ssl_CreateCipherSpec(sslSocket *ss, CipherSpecDirection direction) +ssl_CreateCipherSpec(sslSocket *ss, SSLSecretDirection direction) { ssl3CipherSpec *spec = PORT_ZNew(ssl3CipherSpec); if (!spec) { @@ -159,7 +159,7 @@ ssl_SaveCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) /* Called from ssl3_InitState. */ /* Caller must hold the SpecWriteLock. */ SECStatus -ssl_SetupNullCipherSpec(sslSocket *ss, CipherSpecDirection dir) +ssl_SetupNullCipherSpec(sslSocket *ss, SSLSecretDirection dir) { ssl3CipherSpec *spec; @@ -187,7 +187,7 @@ ssl_SetupNullCipherSpec(sslSocket *ss, CipherSpecDirection dir) dtls_InitRecvdRecords(&spec->recvdRecords); ssl_SaveCipherSpec(ss, spec); - if (dir == CipherSpecRead) { + if (dir == ssl_secret_read) { ss->ssl3.crSpec = spec; } else { ss->ssl3.cwSpec = spec; @@ -259,13 +259,13 @@ ssl_DestroyCipherSpecs(PRCList *list) } void -ssl_CipherSpecReleaseByEpoch(sslSocket *ss, CipherSpecDirection dir, +ssl_CipherSpecReleaseByEpoch(sslSocket *ss, SSLSecretDirection dir, DTLSEpoch epoch) { ssl3CipherSpec *spec; SSL_TRC(10, ("%d: SSL[%d]: releasing %s cipher spec for epoch %d", SSL_GETPID(), ss->fd, - (dir == CipherSpecRead) ? "read" : "write", epoch)); + (dir == ssl_secret_read) ? "read" : "write", epoch)); spec = ssl_FindCipherSpecByEpoch(ss, dir, epoch); if (spec) { diff --git a/security/nss/lib/ssl/sslspec.h b/security/nss/lib/ssl/sslspec.h index b256017553..ca9ef540fb 100644 --- a/security/nss/lib/ssl/sslspec.h +++ b/security/nss/lib/ssl/sslspec.h @@ -19,13 +19,8 @@ typedef enum { TrafficKeyApplicationData = 3 } TrafficKeyType; -typedef enum { - CipherSpecRead, - CipherSpecWrite, -} CipherSpecDirection; - #define SPEC_DIR(spec) \ - ((spec->direction == CipherSpecRead) ? "read" : "write") + ((spec->direction == ssl_secret_read) ? "read" : "write") typedef struct ssl3CipherSpecStr ssl3CipherSpec; typedef struct ssl3BulkCipherDefStr ssl3BulkCipherDef; @@ -106,20 +101,20 @@ typedef struct { typedef SECStatus (*SSLCipher)(void *context, unsigned char *out, - int *outlen, - int maxout, + unsigned int *outlen, + unsigned int maxout, const unsigned char *in, - int inlen); + unsigned int inlen); typedef SECStatus (*SSLAEADCipher)( - ssl3KeyMaterial *keys, + const ssl3KeyMaterial *keys, PRBool doDecrypt, unsigned char *out, - int *outlen, - int maxout, + unsigned int *outlen, + unsigned int maxout, const unsigned char *in, - int inlen, + unsigned int inlen, const unsigned char *additionalData, - int additionalDataLen); + unsigned int additionalDataLen); /* The DTLS anti-replay window in number of packets. Defined here because we * need it in the cipher spec. Note that this is a ring buffer but left and @@ -146,7 +141,7 @@ struct ssl3CipherSpecStr { PRCList link; PRUint8 refCt; - CipherSpecDirection direction; + SSLSecretDirection direction; SSL3ProtocolVersion version; SSL3ProtocolVersion recordVersion; @@ -184,17 +179,17 @@ const ssl3BulkCipherDef *ssl_GetBulkCipherDef(const ssl3CipherSuiteDef *cipher_d const ssl3MACDef *ssl_GetMacDefByAlg(SSL3MACAlgorithm mac); const ssl3MACDef *ssl_GetMacDef(const sslSocket *ss, const ssl3CipherSuiteDef *suiteDef); -ssl3CipherSpec *ssl_CreateCipherSpec(sslSocket *ss, CipherSpecDirection direction); +ssl3CipherSpec *ssl_CreateCipherSpec(sslSocket *ss, SSLSecretDirection direction); void ssl_SaveCipherSpec(sslSocket *ss, ssl3CipherSpec *spec); void ssl_CipherSpecAddRef(ssl3CipherSpec *spec); void ssl_CipherSpecRelease(ssl3CipherSpec *spec); void ssl_DestroyCipherSpecs(PRCList *list); -SECStatus ssl_SetupNullCipherSpec(sslSocket *ss, CipherSpecDirection dir); +SECStatus ssl_SetupNullCipherSpec(sslSocket *ss, SSLSecretDirection dir); ssl3CipherSpec *ssl_FindCipherSpecByEpoch(sslSocket *ss, - CipherSpecDirection direction, + SSLSecretDirection direction, DTLSEpoch epoch); -void ssl_CipherSpecReleaseByEpoch(sslSocket *ss, CipherSpecDirection direction, +void ssl_CipherSpecReleaseByEpoch(sslSocket *ss, SSLSecretDirection direction, DTLSEpoch epoch); #endif /* __sslspec_h_ */ diff --git a/security/nss/lib/ssl/sslt.h b/security/nss/lib/ssl/sslt.h index bd32a6e180..d389a6a2e1 100644 --- a/security/nss/lib/ssl/sslt.h +++ b/security/nss/lib/ssl/sslt.h @@ -43,6 +43,11 @@ typedef enum { ssl_ct_ack = 25 } SSLContentType; +typedef enum { + ssl_secret_read = 1, + ssl_secret_write = 2, +} SSLSecretDirection; + typedef struct SSL3StatisticsStr { /* statistics from ssl3_SendClientHello (sch) */ long sch_sid_cache_hits; @@ -328,6 +333,9 @@ typedef struct SSLChannelInfoStr { /* Preliminary channel info */ #define ssl_preinfo_version (1U << 0) #define ssl_preinfo_cipher_suite (1U << 1) +#define ssl_preinfo_0rtt_cipher_suite (1U << 2) +/* ssl_preinfo_all doesn't contain ssl_preinfo_0rtt_cipher_suite because that + * field is only set if 0-RTT is sent (client) or accepted (server). */ #define ssl_preinfo_all (ssl_preinfo_version | ssl_preinfo_cipher_suite) typedef struct SSLPreliminaryChannelInfoStr { @@ -359,6 +367,13 @@ typedef struct SSLPreliminaryChannelInfoStr { * resume this session. */ PRUint32 maxEarlyDataSize; + /* The following fields were added in NSS 3.39. */ + /* This reports the cipher suite used for 0-RTT if it sent or accepted. For + * a client, this is set earlier than |cipherSuite|, and will match that + * value if 0-RTT is accepted by the server. The server only sets this + * after accepting 0-RTT, so this will contain the same value. */ + PRUint16 zeroRttCipherSuite; + /* When adding new fields to this structure, please document the * NSS version in which they were added. */ } SSLPreliminaryChannelInfo; @@ -407,6 +422,12 @@ typedef struct SSLCipherSuiteInfoStr { * this instead of |authAlgorithm|. */ SSLAuthType authType; + /* The following fields were added in NSS 3.39. */ + /* This reports the hash function used in the TLS KDF, or HKDF for TLS 1.3. + * For suites defined for versions of TLS earlier than TLS 1.2, this reports + * ssl_hash_none. */ + SSLHashType kdfHash; + /* When adding new fields to this structure, please document the * NSS version in which they were added. */ } SSLCipherSuiteInfo; @@ -450,6 +471,7 @@ typedef enum { ssl_tls13_psk_key_exchange_modes_xtn = 45, ssl_tls13_ticket_early_data_info_xtn = 46, /* Deprecated. */ ssl_tls13_certificate_authorities_xtn = 47, + ssl_tls13_post_handshake_auth_xtn = 49, ssl_signature_algorithms_cert_xtn = 50, ssl_tls13_key_share_xtn = 51, ssl_next_proto_nego_xtn = 13172, /* Deprecated. */ diff --git a/security/nss/lib/ssl/tls13con.c b/security/nss/lib/ssl/tls13con.c index 10c4498033..7046180700 100644 --- a/security/nss/lib/ssl/tls13con.c +++ b/security/nss/lib/ssl/tls13con.c @@ -26,20 +26,26 @@ #include "tls13hashstate.h" static SECStatus tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch, - CipherSpecDirection install, + SSLSecretDirection install, PRBool deleteSecret); -static SECStatus tls13_AESGCM( - ssl3KeyMaterial *keys, - PRBool doDecrypt, - unsigned char *out, int *outlen, int maxout, - const unsigned char *in, int inlen, - const unsigned char *additionalData, int additionalDataLen); -static SECStatus tls13_ChaCha20Poly1305( - ssl3KeyMaterial *keys, - PRBool doDecrypt, - unsigned char *out, int *outlen, int maxout, - const unsigned char *in, int inlen, - const unsigned char *additionalData, int additionalDataLen); +static SECStatus tls13_AESGCM(const ssl3KeyMaterial *keys, + PRBool doDecrypt, + unsigned char *out, + unsigned int *outlen, + unsigned int maxout, + const unsigned char *in, + unsigned int inlen, + const unsigned char *additionalData, + unsigned int additionalDataLen); +static SECStatus tls13_ChaCha20Poly1305(const ssl3KeyMaterial *keys, + PRBool doDecrypt, + unsigned char *out, + unsigned int *outlen, + unsigned int maxout, + const unsigned char *in, + unsigned int inlen, + const unsigned char *additionalData, + unsigned int additionalDataLen); static SECStatus tls13_SendServerHelloSequence(sslSocket *ss); static SECStatus tls13_SendEncryptedExtensions(sslSocket *ss); static void tls13_SetKeyExchangeType(sslSocket *ss, const sslNamedGroupDef *group); @@ -56,6 +62,7 @@ static SECStatus tls13_SendCertificate(sslSocket *ss); static SECStatus tls13_HandleCertificate( sslSocket *ss, PRUint8 *b, PRUint32 length); static SECStatus tls13_ReinjectHandshakeTranscript(sslSocket *ss); +static SECStatus tls13_SendCertificateRequest(sslSocket *ss); static SECStatus tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length); static SECStatus @@ -104,6 +111,9 @@ static SECStatus tls13_ComputeFinished( PRBool sending, PRUint8 *output, unsigned int *outputLen, unsigned int maxOutputLen); static SECStatus tls13_SendClientSecondRound(sslSocket *ss); +static SECStatus tls13_SendClientSecondFlight(sslSocket *ss, + PRBool sendClientCert, + SSL3AlertDescription *sendAlert); static SECStatus tls13_FinishHandshake(sslSocket *ss); const char kHkdfLabelClient[] = "c"; @@ -289,7 +299,7 @@ tls13_GetHashSize(const sslSocket *ss) return tls13_GetHashSizeForHash(tls13_GetHash(ss)); } -static CK_MECHANISM_TYPE +CK_MECHANISM_TYPE tls13_GetHkdfMechanismForHash(SSLHashType hash) { switch (hash) { @@ -406,7 +416,7 @@ SSL_SendAdditionalKeyShares(PRFileDesc *fd, unsigned int count) * Called from ssl3_SendClientHello. */ SECStatus -tls13_SetupClientHello(sslSocket *ss) +tls13_SetupClientHello(sslSocket *ss, sslClientHelloType chType) { unsigned int i; SSL3Statistics *ssl3stats = SSL_GetStatistics(); @@ -417,17 +427,24 @@ tls13_SetupClientHello(sslSocket *ss) PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); - PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs)); - /* Do encrypted SNI. This may create a key share as a side effect. */ + /* Do encrypted SNI. + * Note: this makes a new key even though we don't need one. + * Maybe remove this in future for efficiency. */ rv = tls13_ClientSetupESNI(ss); if (rv != SECSuccess) { return SECFailure; } + /* Everything below here is only run on the first CH. */ + if (chType != client_hello_initial) { + return SECSuccess; + } + /* Select the first enabled group. * TODO(ekr@rtfm.com): be smarter about offering the group * that the other side negotiated if we are resuming. */ + PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs)); for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { if (!ss->namedGroupPreferences[i]) { continue; @@ -588,13 +605,13 @@ loser: } static PRBool -tls13_UseServerSecret(sslSocket *ss, CipherSpecDirection direction) +tls13_UseServerSecret(sslSocket *ss, SSLSecretDirection direction) { - return ss->sec.isServer == (direction == CipherSpecWrite); + return ss->sec.isServer == (direction == ssl_secret_write); } static PK11SymKey ** -tls13_TrafficSecretRef(sslSocket *ss, CipherSpecDirection direction) +tls13_TrafficSecretRef(sslSocket *ss, SSLSecretDirection direction) { if (tls13_UseServerSecret(ss, direction)) { return &ss->ssl3.hs.serverTrafficSecret; @@ -603,7 +620,7 @@ tls13_TrafficSecretRef(sslSocket *ss, CipherSpecDirection direction) } SECStatus -tls13_UpdateTrafficKeys(sslSocket *ss, CipherSpecDirection direction) +tls13_UpdateTrafficKeys(sslSocket *ss, SSLSecretDirection direction) { PK11SymKey **secret; PK11SymKey *updatedSecret; @@ -626,7 +643,7 @@ tls13_UpdateTrafficKeys(sslSocket *ss, CipherSpecDirection direction) *secret = updatedSecret; ssl_GetSpecReadLock(ss); - if (direction == CipherSpecRead) { + if (direction == ssl_secret_read) { epoch = ss->ssl3.crSpec->epoch; } else { epoch = ss->ssl3.cwSpec->epoch; @@ -640,6 +657,11 @@ tls13_UpdateTrafficKeys(sslSocket *ss, CipherSpecDirection direction) } ++epoch; + if (ss->secretCallback) { + ss->secretCallback(ss->fd, epoch, direction, updatedSecret, + ss->secretCallbackArg); + } + rv = tls13_SetCipherSpec(ss, epoch, direction, PR_FALSE); if (rv != SECSuccess) { FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); @@ -698,7 +720,7 @@ tls13_SendKeyUpdate(sslSocket *ss, tls13KeyUpdateRequest request, PRBool buffer) } ssl_ReleaseXmitBufLock(ss); - rv = tls13_UpdateTrafficKeys(ss, CipherSpecWrite); + rv = tls13_UpdateTrafficKeys(ss, ssl_secret_write); if (rv != SECSuccess) { goto loser; /* error code set by tls13_UpdateTrafficKeys */ } @@ -791,7 +813,7 @@ tls13_HandleKeyUpdate(sslSocket *ss, PRUint8 *b, unsigned int length) return SECFailure; } - rv = tls13_UpdateTrafficKeys(ss, CipherSpecRead); + rv = tls13_UpdateTrafficKeys(ss, ssl_secret_read); if (rv != SECSuccess) { return SECFailure; /* Error code set by tls13_UpdateTrafficKeys. */ } @@ -820,6 +842,56 @@ tls13_HandleKeyUpdate(sslSocket *ss, PRUint8 *b, unsigned int length) return SECSuccess; } +SECStatus +SSLExp_SendCertificateRequest(PRFileDesc *fd) +{ + SECStatus rv; + sslSocket *ss = ssl_FindSocket(fd); + if (!ss) { + return SECFailure; + } + + /* Not supported. */ + if (IS_DTLS(ss)) { + PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION); + return SECFailure; + } + + if (!ss->firstHsDone || ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + if (ss->ssl3.clientCertRequested) { + PORT_SetError(PR_WOULD_BLOCK_ERROR); + return SECFailure; + } + + rv = TLS13_CHECK_HS_STATE(ss, SEC_ERROR_INVALID_ARGS, + idle_handshake); + if (rv != SECSuccess) { + return SECFailure; + } + + if (!ssl3_ExtensionNegotiated(ss, ssl_tls13_post_handshake_auth_xtn)) { + PORT_SetError(SSL_ERROR_MISSING_POST_HANDSHAKE_AUTH_EXTENSION); + return SECFailure; + } + + ssl_GetSSL3HandshakeLock(ss); + + rv = tls13_SendCertificateRequest(ss); + if (rv == SECSuccess) { + ssl_GetXmitBufLock(ss); + rv = ssl3_FlushHandshake(ss, 0); + ssl_ReleaseXmitBufLock(ss); + ss->ssl3.clientCertRequested = PR_TRUE; + } + + ssl_ReleaseSSL3HandshakeLock(ss); + return rv; +} + SECStatus tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length) { @@ -909,13 +981,13 @@ tls13_RecoverWrappedSharedSecret(sslSocket *ss, sslSessionID *sid) wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; /* unwrap the "master secret" which is actually RMS. */ - ss->ssl3.hs.resumptionMasterSecret = PK11_UnwrapSymKeyWithFlags( + ss->ssl3.hs.resumptionMasterSecret = ssl_unwrapSymKey( wrapKey, sid->u.ssl3.masterWrapMech, NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, tls13_GetHashSizeForHash(hashType), - CKF_SIGN | CKF_VERIFY); + CKF_SIGN | CKF_VERIFY, ss->pkcs11PinArg); PK11_FreeSymKey(wrapKey); if (!ss->ssl3.hs.resumptionMasterSecret) { return SECFailure; @@ -1030,6 +1102,13 @@ tls13_DeriveEarlySecrets(sslSocket *ss) return SECFailure; } + if (ss->secretCallback) { + ss->secretCallback(ss->fd, (PRUint16)TrafficKeyEarlyApplicationData, + ss->sec.isServer ? ssl_secret_read : ssl_secret_write, + ss->ssl3.hs.clientEarlyTrafficSecret, + ss->secretCallbackArg); + } + rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret, NULL, kHkdfLabelEarlyExporterSecret, keylogLabelEarlyExporterSecret, @@ -1098,6 +1177,18 @@ tls13_ComputeHandshakeSecrets(sslSocket *ss) return rv; } + if (ss->secretCallback) { + SSLSecretDirection dir = + ss->sec.isServer ? ssl_secret_read : ssl_secret_write; + ss->secretCallback(ss->fd, (PRUint16)TrafficKeyHandshake, dir, + ss->ssl3.hs.clientHsTrafficSecret, + ss->secretCallbackArg); + dir = ss->sec.isServer ? ssl_secret_write : ssl_secret_read; + ss->secretCallback(ss->fd, (PRUint16)TrafficKeyHandshake, dir, + ss->ssl3.hs.serverHsTrafficSecret, + ss->secretCallbackArg); + } + SSL_TRC(5, ("%d: TLS13[%d]: compute master secret (%s)", SSL_GETPID(), ss->fd, SSL_ROLE(ss))); @@ -1148,6 +1239,18 @@ tls13_ComputeApplicationSecrets(sslSocket *ss) return SECFailure; } + if (ss->secretCallback) { + SSLSecretDirection dir = + ss->sec.isServer ? ssl_secret_read : ssl_secret_write; + ss->secretCallback(ss->fd, (PRUint16)TrafficKeyApplicationData, + dir, ss->ssl3.hs.clientTrafficSecret, + ss->secretCallbackArg); + dir = ss->sec.isServer ? ssl_secret_write : ssl_secret_read; + ss->secretCallback(ss->fd, (PRUint16)TrafficKeyApplicationData, + dir, ss->ssl3.hs.serverTrafficSecret, + ss->secretCallbackArg); + } + rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret, NULL, kHkdfLabelExporterMasterSecret, keylogLabelExporterSecret, @@ -1294,6 +1397,8 @@ tls13_NegotiateZeroRtt(sslSocket *ss, const sslSessionID *sid) PORT_Assert(ss->statelessResume); ss->ssl3.hs.zeroRttState = ssl_0rtt_accepted; ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_none; + ss->ssl3.hs.zeroRttSuite = ss->ssl3.hs.cipher_suite; + ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_0rtt_cipher_suite; } /* Check if the offered group is acceptable. */ @@ -2101,8 +2206,27 @@ tls13_SendCertificateRequest(sslSocket *ss) /* We should always have at least one of these. */ PORT_Assert(SSL_BUFFER_LEN(&extensionBuf) > 0); + /* Create a new request context for post-handshake authentication */ + if (ss->firstHsDone) { + PRUint8 context[16]; + SECItem contextItem = { siBuffer, context, sizeof(context) }; + + rv = PK11_GenerateRandom(context, sizeof(context)); + if (rv != SECSuccess) { + goto loser; + } + + SECITEM_FreeItem(&ss->xtnData.certReqContext, PR_FALSE); + rv = SECITEM_CopyItem(NULL, &ss->xtnData.certReqContext, &contextItem); + if (rv != SECSuccess) { + FATAL_ERROR(ss, SEC_ERROR_NO_MEMORY, internal_error); + goto loser; + } + } + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_certificate_request, - 1 + 0 + /* empty request context */ + 1 + /* request context length */ + ss->xtnData.certReqContext.len + 2 + /* extension length */ SSL_BUFFER_LEN(&extensionBuf)); if (rv != SECSuccess) { @@ -2110,7 +2234,8 @@ tls13_SendCertificateRequest(sslSocket *ss) } /* Context. */ - rv = ssl3_AppendHandshakeNumber(ss, 0, 1); + rv = ssl3_AppendHandshakeVariable(ss, ss->xtnData.certReqContext.data, + ss->xtnData.certReqContext.len, 1); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */ } @@ -2198,7 +2323,7 @@ tls13_HandleHelloRetryRequest(sslSocket *ss, const PRUint8 *savedMsg, /* Restore the null cipher spec for writing. */ ssl_GetSpecWriteLock(ss); ssl_CipherSpecRelease(ss->ssl3.cwSpec); - ss->ssl3.cwSpec = ssl_FindCipherSpecByEpoch(ss, CipherSpecWrite, + ss->ssl3.cwSpec = ssl_FindCipherSpecByEpoch(ss, ssl_secret_write, TrafficKeyClearText); PORT_Assert(ss->ssl3.cwSpec); ssl_ReleaseSpecWriteLock(ss); @@ -2274,25 +2399,49 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length) PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); /* Client */ - rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, - wait_cert_request); + if (ss->opt.enablePostHandshakeAuth) { + rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, + wait_cert_request, idle_handshake); + } else { + rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, + wait_cert_request); + } if (rv != SECSuccess) { return SECFailure; } - PORT_Assert(ss->ssl3.clientCertChain == NULL); - PORT_Assert(ss->ssl3.clientCertificate == NULL); - PORT_Assert(ss->ssl3.clientPrivateKey == NULL); - PORT_Assert(!ss->ssl3.hs.clientCertRequested); + if (ss->firstHsDone) { + /* clean up anything left from previous handshake. */ + if (ss->ssl3.clientCertChain != NULL) { + CERT_DestroyCertificateList(ss->ssl3.clientCertChain); + ss->ssl3.clientCertChain = NULL; + } + if (ss->ssl3.clientCertificate != NULL) { + CERT_DestroyCertificate(ss->ssl3.clientCertificate); + ss->ssl3.clientCertificate = NULL; + } + if (ss->ssl3.clientPrivateKey != NULL) { + SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); + ss->ssl3.clientPrivateKey = NULL; + } + SECITEM_FreeItem(&ss->xtnData.certReqContext, PR_FALSE); + ss->xtnData.certReqContext.data = NULL; + } else { + PORT_Assert(ss->ssl3.clientCertChain == NULL); + PORT_Assert(ss->ssl3.clientCertificate == NULL); + PORT_Assert(ss->ssl3.clientPrivateKey == NULL); + PORT_Assert(!ss->ssl3.hs.clientCertRequested); + PORT_Assert(ss->xtnData.certReqContext.data == NULL); + } rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length); if (rv != SECSuccess) { return SECFailure; } - /* We don't support post-handshake client auth, the certificate request - * context must always be empty. */ - if (context.len > 0) { + /* Unless it is a post-handshake client auth, the certificate + * request context must be empty. */ + if (!ss->firstHsDone && context.len > 0) { FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST, illegal_parameter); return SECFailure; } @@ -2326,7 +2475,35 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length) } ss->ssl3.hs.clientCertRequested = PR_TRUE; - TLS13_SET_HS_STATE(ss, wait_server_cert); + + if (ss->firstHsDone) { + SSL3AlertDescription sendAlert = no_alert; + + /* Request a client certificate. */ + rv = ssl3_CompleteHandleCertificateRequest( + ss, ss->xtnData.sigSchemes, ss->xtnData.numSigSchemes, + &ss->xtnData.certReqAuthorities); + if (rv != SECSuccess) { + FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); + return rv; + } + + ssl_GetXmitBufLock(ss); + rv = tls13_SendClientSecondFlight(ss, !ss->ssl3.sendEmptyCert, + &sendAlert); + ssl_ReleaseXmitBufLock(ss); + if (rv != SECSuccess) { + if (sendAlert != no_alert) { + FATAL_ERROR(ss, PORT_GetError(), sendAlert); + } else { + LOG_ERROR(ss, PORT_GetError()); + } + return SECFailure; + } + PORT_Assert(ss->ssl3.hs.ws == idle_handshake); + } else { + TLS13_SET_HS_STATE(ss, wait_server_cert); + } return SECSuccess; } @@ -2348,7 +2525,7 @@ tls13_SendEncryptedServerSequence(sslSocket *ss) } rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, - CipherSpecWrite, PR_FALSE); + ssl_secret_write, PR_FALSE); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -2458,7 +2635,7 @@ tls13_SendServerHelloSequence(sslSocket *ss) } rv = tls13_SetCipherSpec(ss, TrafficKeyApplicationData, - CipherSpecWrite, PR_FALSE); + ssl_secret_write, PR_FALSE); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -2470,7 +2647,7 @@ tls13_SendServerHelloSequence(sslSocket *ss) } if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) { rv = tls13_SetCipherSpec(ss, TrafficKeyEarlyApplicationData, - CipherSpecRead, PR_TRUE); + ssl_secret_read, PR_TRUE); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -2482,7 +2659,7 @@ tls13_SendServerHelloSequence(sslSocket *ss) rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, - CipherSpecRead, PR_FALSE); + ssl_secret_read, PR_FALSE); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -2591,11 +2768,11 @@ tls13_HandleServerHelloPart2(sslSocket *ss) /* When we send 0-RTT, we saved the null spec in case we needed it to * send another ClientHello in response to a HelloRetryRequest. Now * that we won't be receiving a HelloRetryRequest, release the spec. */ - ssl_CipherSpecReleaseByEpoch(ss, CipherSpecWrite, TrafficKeyClearText); + ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_write, TrafficKeyClearText); } rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, - CipherSpecRead, PR_FALSE); + ssl_secret_read, PR_FALSE); if (rv != SECSuccess) { FATAL_ERROR(ss, SSL_ERROR_INIT_CIPHER_SUITE_FAILURE, internal_error); return SECFailure; @@ -2862,8 +3039,13 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length) PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); if (ss->sec.isServer) { - rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, - wait_client_cert); + if (ss->ssl3.clientCertRequested) { + rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, + idle_handshake); + } else { + rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, + wait_client_cert); + } } else { rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, wait_cert_request, wait_server_cert); @@ -2873,7 +3055,7 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length) /* We can ignore any other cleartext from the client. */ if (ss->sec.isServer && IS_DTLS(ss)) { - ssl_CipherSpecReleaseByEpoch(ss, CipherSpecRead, TrafficKeyClearText); + ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read, TrafficKeyClearText); dtls_ReceivedFirstMessageInFlight(ss); } /* Process the context string */ @@ -2881,10 +3063,12 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length) if (rv != SECSuccess) return SECFailure; - if (context.len) { - /* The context string MUST be empty */ - FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE, illegal_parameter); - return SECFailure; + if (ss->ssl3.clientCertRequested) { + PORT_Assert(ss->sec.isServer); + if (SECITEM_CompareItem(&context, &ss->xtnData.certReqContext) != 0) { + FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE, illegal_parameter); + return SECFailure; + } } rv = ssl3_ConsumeHandshakeVariable(ss, &certList, 3, &b, &length); @@ -3125,6 +3309,25 @@ tls13_DeriveSecretWrap(sslSocket *ss, PK11SymKey *key, return SECSuccess; } +SECStatus +SSLExp_SecretCallback(PRFileDesc *fd, SSLSecretCallback cb, void *arg) +{ + sslSocket *ss = ssl_FindSocket(fd); + if (!ss) { + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SecretCallback", + SSL_GETPID(), fd)); + return SECFailure; + } + + ssl_Get1stHandshakeLock(ss); + ssl_GetSSL3HandshakeLock(ss); + ss->secretCallback = cb; + ss->secretCallbackArg = arg; + ssl_ReleaseSSL3HandshakeLock(ss); + ssl_Release1stHandshakeLock(ss); + return SECSuccess; +} + /* Derive traffic keys for the next cipher spec in the queue. */ static SECStatus tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *spec, @@ -3251,7 +3454,7 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) /* We want to keep read cipher specs around longer because * there are cases where we might get either epoch N or * epoch N+1. */ - if (IS_DTLS(ss) && spec->direction == CipherSpecRead) { + if (IS_DTLS(ss) && spec->direction == ssl_secret_read) { ssl_CipherSpecAddRef(spec); } @@ -3274,7 +3477,7 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) /* The record size limit is reduced by one so that the remainder of the * record handling code can use the same checks for all versions. */ if (ssl3_ExtensionNegotiated(ss, ssl_record_size_limit_xtn)) { - spec->recordSizeLimit = ((spec->direction == CipherSpecRead) + spec->recordSizeLimit = ((spec->direction == ssl_secret_read) ? ss->opt.recordSizeLimit : ss->xtnData.recordSizeLimit) - 1; @@ -3310,7 +3513,7 @@ tls13_SetAlertCipherSpec(sslSocket *ss) } rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, - CipherSpecWrite, PR_FALSE); + ssl_secret_write, PR_FALSE); if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -3325,7 +3528,7 @@ tls13_SetAlertCipherSpec(sslSocket *ss) */ static SECStatus tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch, - CipherSpecDirection direction, PRBool deleteSecret) + SSLSecretDirection direction, PRBool deleteSecret) { TrafficKeyType type; SECStatus rv; @@ -3364,7 +3567,7 @@ tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch, } /* Now that we've set almost everything up, finally cut over. */ - specp = (direction == CipherSpecRead) ? &ss->ssl3.crSpec : &ss->ssl3.cwSpec; + specp = (direction == ssl_secret_read) ? &ss->ssl3.crSpec : &ss->ssl3.cwSpec; ssl_GetSpecWriteLock(ss); ssl_CipherSpecRelease(*specp); /* May delete old cipher. */ *specp = spec; /* Overwrite. */ @@ -3373,11 +3576,6 @@ tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch, SSL_TRC(3, ("%d: TLS13[%d]: %s installed key for epoch=%d (%s) dir=%s", SSL_GETPID(), ss->fd, SSL_ROLE(ss), spec->epoch, spec->phase, SPEC_DIR(spec))); - - if (ss->ssl3.changedCipherSpecFunc) { - ss->ssl3.changedCipherSpecFunc(ss->ssl3.changedCipherSpecArg, - direction == CipherSpecWrite, spec); - } return SECSuccess; loser: @@ -3526,7 +3724,7 @@ tls13_DestroyEarlyData(PRCList *list) * See RFC 5288 and https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-04#section-2 */ static void -tls13_WriteNonce(ssl3KeyMaterial *keys, +tls13_WriteNonce(const ssl3KeyMaterial *keys, const unsigned char *seqNumBuf, unsigned int seqNumLen, unsigned char *nonce, unsigned int nonceLen) { @@ -3549,41 +3747,35 @@ tls13_WriteNonce(ssl3KeyMaterial *keys, * a sequence number. In TLS 1.3 there is no additional data so this value is * just the encoded sequence number. */ -static SECStatus -tls13_AEAD(ssl3KeyMaterial *keys, PRBool doDecrypt, - unsigned char *out, int *outlen, int maxout, - const unsigned char *in, int inlen, +SECStatus +tls13_AEAD(const ssl3KeyMaterial *keys, PRBool doDecrypt, + unsigned char *out, unsigned int *outlen, unsigned int maxout, + const unsigned char *in, unsigned int inlen, CK_MECHANISM_TYPE mechanism, unsigned char *aeadParams, unsigned int aeadParamLength) { - SECStatus rv; - unsigned int uOutLen = 0; SECItem param = { siBuffer, aeadParams, aeadParamLength }; if (doDecrypt) { - rv = PK11_Decrypt(keys->key, mechanism, ¶m, - out, &uOutLen, maxout, in, inlen); - } else { - rv = PK11_Encrypt(keys->key, mechanism, ¶m, - out, &uOutLen, maxout, in, inlen); + return PK11_Decrypt(keys->key, mechanism, ¶m, + out, outlen, maxout, in, inlen); } - *outlen = (int)uOutLen; - - return rv; + return PK11_Encrypt(keys->key, mechanism, ¶m, + out, outlen, maxout, in, inlen); } static SECStatus -tls13_AESGCM(ssl3KeyMaterial *keys, +tls13_AESGCM(const ssl3KeyMaterial *keys, PRBool doDecrypt, unsigned char *out, - int *outlen, - int maxout, + unsigned int *outlen, + unsigned int maxout, const unsigned char *in, - int inlen, + unsigned int inlen, const unsigned char *additionalData, - int additionalDataLen) + unsigned int additionalDataLen) { CK_GCM_PARAMS gcmParams; unsigned char nonce[12]; @@ -3604,11 +3796,11 @@ tls13_AESGCM(ssl3KeyMaterial *keys, } static SECStatus -tls13_ChaCha20Poly1305(ssl3KeyMaterial *keys, PRBool doDecrypt, - unsigned char *out, int *outlen, int maxout, - const unsigned char *in, int inlen, +tls13_ChaCha20Poly1305(const ssl3KeyMaterial *keys, PRBool doDecrypt, + unsigned char *out, unsigned int *outlen, unsigned int maxout, + const unsigned char *in, unsigned int inlen, const unsigned char *additionalData, - int additionalDataLen) + unsigned int additionalDataLen) { CK_NSS_AEAD_PARAMS aeadParams; unsigned char nonce[12]; @@ -3937,6 +4129,10 @@ tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length) } } + if (ss->ssl3.clientCertRequested) { + PORT_Assert(ss->sec.isServer); + ss->ssl3.clientCertRequested = PR_FALSE; + } TLS13_SET_HS_STATE(ss, wait_finished); return SECSuccess; @@ -4238,26 +4434,32 @@ tls13_ServerHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length) SSL_TRC(3, ("%d: TLS13[%d]: server handle finished handshake", SSL_GETPID(), ss->fd)); - rv = tls13_CommonHandleFinished(ss, ss->ssl3.hs.clientHsTrafficSecret, + rv = tls13_CommonHandleFinished(ss, + ss->firstHsDone ? ss->ssl3.hs.clientTrafficSecret : ss->ssl3.hs.clientHsTrafficSecret, b, length); if (rv != SECSuccess) { return SECFailure; } + if (ss->firstHsDone) { + TLS13_SET_HS_STATE(ss, idle_handshake); + return SECSuccess; + } + if (!tls13_ShouldRequestClientAuth(ss) && (ss->ssl3.hs.zeroRttState != ssl_0rtt_done)) { dtls_ReceivedFirstMessageInFlight(ss); } rv = tls13_SetCipherSpec(ss, TrafficKeyApplicationData, - CipherSpecRead, PR_FALSE); + ssl_secret_read, PR_FALSE); if (rv != SECSuccess) { FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); return SECFailure; } if (IS_DTLS(ss)) { - ssl_CipherSpecReleaseByEpoch(ss, CipherSpecRead, TrafficKeyClearText); + ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read, TrafficKeyClearText); /* We need to keep the handshake cipher spec so we can * read re-transmitted client Finished. */ rv = dtls_StartTimer(ss, ss->ssl3.hs.hdTimer, @@ -4361,7 +4563,7 @@ tls13_SendClientSecondFlight(sslSocket *ss, PRBool sendClientCert, } } - rv = tls13_SendFinished(ss, ss->ssl3.hs.clientHsTrafficSecret); + rv = tls13_SendFinished(ss, ss->firstHsDone ? ss->ssl3.hs.clientTrafficSecret : ss->ssl3.hs.clientHsTrafficSecret); if (rv != SECSuccess) { return SECFailure; /* err code was set. */ } @@ -4404,7 +4606,8 @@ tls13_SendClientSecondRound(sslSocket *ss) " certificate authentication is still pending.", SSL_GETPID(), ss->fd)); ss->ssl3.hs.restartTarget = tls13_SendClientSecondRound; - return SECWouldBlock; + PORT_SetError(PR_WOULD_BLOCK_ERROR); + return SECFailure; } rv = tls13_ComputeApplicationSecrets(ss); @@ -4432,14 +4635,14 @@ tls13_SendClientSecondRound(sslSocket *ss) } rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, - CipherSpecWrite, PR_FALSE); + ssl_secret_write, PR_FALSE); if (rv != SECSuccess) { FATAL_ERROR(ss, SSL_ERROR_INIT_CIPHER_SUITE_FAILURE, internal_error); return SECFailure; } rv = tls13_SetCipherSpec(ss, TrafficKeyApplicationData, - CipherSpecRead, PR_FALSE); + ssl_secret_read, PR_FALSE); if (rv != SECSuccess) { FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); return SECFailure; @@ -4457,7 +4660,7 @@ tls13_SendClientSecondRound(sslSocket *ss) return SECFailure; } rv = tls13_SetCipherSpec(ss, TrafficKeyApplicationData, - CipherSpecWrite, PR_FALSE); + ssl_secret_write, PR_FALSE); if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -4815,7 +5018,8 @@ static const struct { { ssl_tls13_supported_versions_xtn, _M3(client_hello, server_hello, hello_retry_request) }, { ssl_record_size_limit_xtn, _M2(client_hello, encrypted_extensions) }, - { ssl_tls13_encrypted_sni_xtn, _M2(client_hello, encrypted_extensions) } + { ssl_tls13_encrypted_sni_xtn, _M2(client_hello, encrypted_extensions) }, + { ssl_tls13_post_handshake_auth_xtn, _M1(client_hello) } }; tls13ExtensionStatus @@ -4924,7 +5128,7 @@ tls13_ProtectRecord(sslSocket *ss, const int tagLen = cipher_def->tag_size; SECStatus rv; - PORT_Assert(cwSpec->direction == CipherSpecWrite); + PORT_Assert(cwSpec->direction == ssl_secret_write); SSL_TRC(3, ("%d: TLS13[%d]: spec=%d epoch=%d (%s) protect 0x%0llx len=%u", SSL_GETPID(), ss->fd, cwSpec, cwSpec->epoch, cwSpec->phase, cwSpec->nextSeqNum, contentLen)); @@ -4948,7 +5152,7 @@ tls13_ProtectRecord(sslSocket *ss, PRBool needsLength; PRUint8 aad[21]; unsigned int aadLen; - int len; + unsigned int len; PORT_Assert(cipher_def->type == type_aead); @@ -5018,7 +5222,7 @@ tls13_UnprotectRecord(sslSocket *ss, *alert = bad_record_mac; /* Default alert for most issues. */ - PORT_Assert(spec->direction == CipherSpecRead); + PORT_Assert(spec->direction == ssl_secret_read); SSL_TRC(3, ("%d: TLS13[%d]: spec=%d epoch=%d (%s) unprotect 0x%0llx len=%u", SSL_GETPID(), ss->fd, spec, spec->epoch, spec->phase, cText->seqNum, cText->buf->len)); @@ -5069,12 +5273,12 @@ tls13_UnprotectRecord(sslSocket *ss, return SECFailure; } rv = spec->aead(&spec->keyMaterial, - PR_TRUE, /* do decrypt */ - plaintext->buf, /* out */ - (int *)&plaintext->len, /* outlen */ - plaintext->space, /* maxout */ - cText->buf->buf, /* in */ - cText->buf->len, /* inlen */ + PR_TRUE, /* do decrypt */ + plaintext->buf, /* out */ + &plaintext->len, /* outlen */ + plaintext->space, /* maxout */ + cText->buf->buf, /* in */ + cText->buf->len, /* inlen */ aad, aadLen); if (rv != SECSuccess) { SSL_TRC(3, @@ -5175,6 +5379,9 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss) ss->ssl3.hs.zeroRttState = ssl_0rtt_sent; ss->ssl3.hs.zeroRttSuite = ss->ssl3.hs.cipher_suite; + /* Note: Reset the preliminary info here rather than just add 0-RTT. We are + * only guessing what might happen at this point.*/ + ss->ssl3.hs.preliminaryInfo = ssl_preinfo_0rtt_cipher_suite; SSL_TRC(3, ("%d: TLS13[%d]: in 0-RTT mode", SSL_GETPID(), ss->fd)); @@ -5203,9 +5410,6 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss) } } - /* Cipher suite already set in tls13_SetupClientHello. */ - ss->ssl3.hs.preliminaryInfo = 0; - rv = tls13_DeriveEarlySecrets(ss); if (rv != SECSuccess) { return SECFailure; @@ -5216,7 +5420,7 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss) ssl_CipherSpecAddRef(ss->ssl3.cwSpec); rv = tls13_SetCipherSpec(ss, TrafficKeyEarlyApplicationData, - CipherSpecWrite, PR_TRUE); + ssl_secret_write, PR_TRUE); if (rv != SECSuccess) { return SECFailure; } @@ -5279,7 +5483,7 @@ tls13_HandleEndOfEarlyData(sslSocket *ss, PRUint8 *b, PRUint32 length) /* We shouldn't be getting any more early data, and if we do, * it is because of reordering and we drop it. */ if (IS_DTLS(ss)) { - ssl_CipherSpecReleaseByEpoch(ss, CipherSpecRead, + ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read, TrafficKeyEarlyApplicationData); dtls_ReceivedFirstMessageInFlight(ss); } @@ -5292,7 +5496,7 @@ tls13_HandleEndOfEarlyData(sslSocket *ss, PRUint8 *b, PRUint32 length) } rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, - CipherSpecRead, PR_FALSE); + ssl_secret_read, PR_FALSE); if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; diff --git a/security/nss/lib/ssl/tls13con.h b/security/nss/lib/ssl/tls13con.h index f3b2cb3905..ed4c4ec787 100644 --- a/security/nss/lib/ssl/tls13con.h +++ b/security/nss/lib/ssl/tls13con.h @@ -52,6 +52,7 @@ SSLHashType tls13_GetHash(const sslSocket *ss); unsigned int tls13_GetHashSizeForHash(SSLHashType hash); unsigned int tls13_GetHashSize(const sslSocket *ss); CK_MECHANISM_TYPE tls13_GetHkdfMechanism(sslSocket *ss); +CK_MECHANISM_TYPE tls13_GetHkdfMechanismForHash(SSLHashType hash); SECStatus tls13_ComputeHash(sslSocket *ss, SSL3Hashes *hashes, const PRUint8 *buf, unsigned int len); SECStatus tls13_ComputeHandshakeHashes(sslSocket *ss, @@ -62,7 +63,7 @@ SECStatus tls13_DeriveSecretNullHash(sslSocket *ss, PK11SymKey *key, PK11SymKey **dest); void tls13_FatalError(sslSocket *ss, PRErrorCode prError, SSL3AlertDescription desc); -SECStatus tls13_SetupClientHello(sslSocket *ss); +SECStatus tls13_SetupClientHello(sslSocket *ss, sslClientHelloType chType); SECStatus tls13_MaybeDo0RTTHandshake(sslSocket *ss); PRInt32 tls13_LimitEarlyData(sslSocket *ss, SSLContentType type, PRInt32 toSend); PRBool tls13_AllowPskCipher(const sslSocket *ss, @@ -130,7 +131,13 @@ SECStatus tls13_SendKeyUpdate(sslSocket *ss, tls13KeyUpdateRequest request, SECStatus SSLExp_KeyUpdate(PRFileDesc *fd, PRBool requestUpdate); PRBool tls13_MaybeTls13(sslSocket *ss); SSLAEADCipher tls13_GetAead(const ssl3BulkCipherDef *cipherDef); +SECStatus tls13_AEAD(const ssl3KeyMaterial *keys, PRBool doDecrypt, + unsigned char *out, unsigned int *outlen, unsigned int maxout, + const unsigned char *in, unsigned int inlen, + CK_MECHANISM_TYPE mechanism, + unsigned char *aeadParams, unsigned int aeadParamLength); void tls13_SetSpecRecordVersion(sslSocket *ss, ssl3CipherSpec *spec); +SECStatus SSLExp_SendCertificateRequest(PRFileDesc *fd); /* Use this instead of FATAL_ERROR when no alert shall be sent. */ #define LOG_ERROR(ss, prError) \ diff --git a/security/nss/lib/ssl/tls13esni.c b/security/nss/lib/ssl/tls13esni.c index e2328769bc..9b635a9cfe 100644 --- a/security/nss/lib/ssl/tls13esni.c +++ b/security/nss/lib/ssl/tls13esni.c @@ -584,6 +584,8 @@ tls13_ClientSetupESNI(sslSocket *ss) const sslNamedGroupDef *group = NULL; PRTime now = PR_Now() / PR_USEC_PER_SEC; + PORT_Assert(!ss->xtnData.esniPrivateKey); + if (!ss->esniKeys) { return SECSuccess; } @@ -721,8 +723,8 @@ tls13_ServerGetEsniAEAD(const sslSocket *ss, PRUint64 suite, } SECStatus -tls13_ServerDecryptEsniXtn(const sslSocket *ss, PRUint8 *in, unsigned int inLen, - PRUint8 *out, int *outLen, int maxLen) +tls13_ServerDecryptEsniXtn(const sslSocket *ss, const PRUint8 *in, unsigned int inLen, + PRUint8 *out, unsigned int *outLen, unsigned int maxLen) { sslReader rdr = SSL_READER(in, inLen); PRUint64 suite; diff --git a/security/nss/lib/ssl/tls13esni.h b/security/nss/lib/ssl/tls13esni.h index 6c52c99525..0fb12d25e3 100644 --- a/security/nss/lib/ssl/tls13esni.h +++ b/security/nss/lib/ssl/tls13esni.h @@ -45,7 +45,7 @@ SECStatus tls13_ComputeESNIKeys(const sslSocket *ss, SECStatus tls13_FormatEsniAADInput(sslBuffer *aadInput, PRUint8 *keyShare, unsigned int keyShareLen); -SECStatus tls13_ServerDecryptEsniXtn(const sslSocket *ss, PRUint8 *in, unsigned int inLen, - PRUint8 *out, int *outLen, int maxLen); +SECStatus tls13_ServerDecryptEsniXtn(const sslSocket *ss, const PRUint8 *in, unsigned int inLen, + PRUint8 *out, unsigned int *outLen, unsigned int maxLen); #endif diff --git a/security/nss/lib/ssl/tls13exthandle.c b/security/nss/lib/ssl/tls13exthandle.c index 8ed18f69cd..9def16d413 100644 --- a/security/nss/lib/ssl/tls13exthandle.c +++ b/security/nss/lib/ssl/tls13exthandle.c @@ -915,6 +915,37 @@ tls13_ServerHandleCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData, return SECSuccess; } +SECStatus +tls13_ClientSendPostHandshakeAuthXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) +{ + SSL_TRC(3, ("%d: TLS13[%d]: send post_handshake_auth extension", + SSL_GETPID(), ss->fd)); + + *added = ss->opt.enablePostHandshakeAuth; + return SECSuccess; +} + +SECStatus +tls13_ServerHandlePostHandshakeAuthXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data) +{ + SSL_TRC(3, ("%d: TLS13[%d]: handle post_handshake_auth extension", + SSL_GETPID(), ss->fd)); + + if (data->len) { + PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); + return SECFailure; + } + + /* Keep track of negotiated extensions. */ + xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_post_handshake_auth_xtn; + + return SECSuccess; +} + /* * enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode; * @@ -1109,7 +1140,7 @@ tls13_ClientSendEsniXtn(const sslSocket *ss, TLSExtensionData *xtnData, ssl3KeyMaterial keyMat; SSLAEADCipher aead; PRUint8 outBuf[1024]; - int outLen; + unsigned int outLen; unsigned int sniStart; unsigned int sniLen; sslBuffer aadInput = SSL_BUFFER_EMPTY; @@ -1263,7 +1294,7 @@ tls13_ServerHandleEsniXtn(const sslSocket *ss, TLSExtensionData *xtnData, { sslReadBuffer buf; PRUint8 *plainText = NULL; - int ptLen; + unsigned int ptLen; SECStatus rv; /* If we are doing < TLS 1.3, then ignore this. */ diff --git a/security/nss/lib/ssl/tls13exthandle.h b/security/nss/lib/ssl/tls13exthandle.h index dd64b44ff4..d36a4f9351 100644 --- a/security/nss/lib/ssl/tls13exthandle.h +++ b/security/nss/lib/ssl/tls13exthandle.h @@ -93,5 +93,11 @@ SECStatus tls13_ClientSendEsniXtn(const sslSocket *ss, TLSExtensionData *xtnData SECStatus tls13_ServerHandleEsniXtn(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data); SECStatus tls13_ClientCheckEsniXtn(sslSocket *ss); +SECStatus tls13_ClientSendPostHandshakeAuthXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); +SECStatus tls13_ServerHandlePostHandshakeAuthXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data); #endif diff --git a/security/nss/lib/ssl/tls13hkdf.c b/security/nss/lib/ssl/tls13hkdf.c index 8fa3375c63..ab546e06f6 100644 --- a/security/nss/lib/ssl/tls13hkdf.c +++ b/security/nss/lib/ssl/tls13hkdf.c @@ -140,14 +140,13 @@ tls13_HkdfExpandLabel(PK11SymKey *prk, SSLHashType baseHash, const char *kLabelPrefix = "tls13 "; const unsigned int kLabelPrefixLen = strlen(kLabelPrefix); - if (handshakeHash) { - if (handshakeHashLen > 255) { - PORT_Assert(0); - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - } else { - PORT_Assert(!handshakeHashLen); + PORT_Assert(prk); + PORT_Assert(keyp); + if ((handshakeHashLen > 255) || + (handshakeHash == NULL && handshakeHashLen > 0) || + (labelLen + kLabelPrefixLen > 255)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } /* @@ -208,7 +207,7 @@ tls13_HkdfExpandLabel(PK11SymKey *prk, SSLHashType baseHash, *keyp = derived; #ifdef TRACE - if (ssl_trace >= 10) { + if (ssl_trace >= 50) { /* Make sure the label is null terminated. */ char labelStr[100]; PORT_Memcpy(labelStr, label, labelLen); diff --git a/security/nss/lib/util/nssutil.h b/security/nss/lib/util/nssutil.h index c8ac78e778..75c32f46c0 100644 --- a/security/nss/lib/util/nssutil.h +++ b/security/nss/lib/util/nssutil.h @@ -19,9 +19,9 @@ * The format of the version string should be * ".[.[.]][ ]" */ -#define NSSUTIL_VERSION "3.43 Beta" +#define NSSUTIL_VERSION "3.44 Beta" #define NSSUTIL_VMAJOR 3 -#define NSSUTIL_VMINOR 43 +#define NSSUTIL_VMINOR 44 #define NSSUTIL_VPATCH 0 #define NSSUTIL_VBUILD 0 #define NSSUTIL_BETA PR_TRUE diff --git a/security/nss/mach b/security/nss/mach index 842c4fd86a..f12b6413ac 100644 --- a/security/nss/mach +++ b/security/nss/mach @@ -39,18 +39,16 @@ def run_tests(test, cycles="standard", env={}, silent=False): subprocess.check_call(command, env=os_env, stdout=stdout, stderr=stderr) class cfAction(argparse.Action): - docker_command = ["docker"] + docker_command = None restorecon = None def __call__(self, parser, args, values, option_string=None): - if not args.noroot: - self.setDockerCommand() + self.setDockerCommand(args) if values: files = [os.path.relpath(os.path.abspath(x), start=cwd) for x in values] else: files = self.modifiedFiles() - files = [os.path.join('/home/worker/nss', x) for x in files] # First check if we can run docker. try: @@ -58,9 +56,16 @@ class cfAction(argparse.Action): subprocess.check_call( self.docker_command + ["images"], stdout=f) except: - print("Please install docker and start the docker daemon.") - sys.exit(1) + self.docker_command = None + if self.docker_command is None: + print("warning: running clang-format directly, which isn't guaranteed to be correct") + command = [cwd + "/automation/clang-format/run_clang_format.sh"] + files + repr(command) + subprocess.call(command) + return + + files = [os.path.join('/home/worker/nss', x) for x in files] docker_image = 'clang-format-service:latest' cf_docker_folder = cwd + "/automation/clang-format" @@ -113,11 +118,17 @@ class cfAction(argparse.Action): subprocess.check_call(command) return - def setDockerCommand(self): + def setDockerCommand(self, args): + from distutils.spawn import find_executable if platform.system() == "Linux": - from distutils.spawn import find_executable - self.restorecon = find_executable('restorecon') - self.docker_command = ["sudo"] + self.docker_command + self.restorecon = find_executable("restorecon") + dcmd = find_executable("docker") + if dcmd is not None: + self.docker_command = [dcmd] + if not args.noroot: + self.docker_command = ["sudo"] + self.docker_command + else: + self.docker_command = None def modifiedFiles(self): files = [] diff --git a/security/nss/nss.gyp b/security/nss/nss.gyp index 3cc3d7b6d7..eb4d63095d 100644 --- a/security/nss/nss.gyp +++ b/security/nss/nss.gyp @@ -106,6 +106,11 @@ 'cmd/shlibsign/shlibsign.gyp:shlibsign', ], 'conditions': [ + [ 'comm_client==1', { + 'dependencies': [ + 'cmd/smimetools/smimetools.gyp:cmsutil', + ], + }], [ 'mozilla_client==0', { 'dependencies': [ 'cmd/crlutil/crlutil.gyp:crlutil', @@ -168,6 +173,7 @@ 'cmd/pk11ectest/pk11ectest.gyp:pk11ectest', 'cmd/pk11gcmtest/pk11gcmtest.gyp:pk11gcmtest', 'cmd/pk11mode/pk11mode.gyp:pk11mode', + 'cmd/pk11importtest/pk11importtest.gyp:pk11importtest', 'cmd/pk1sign/pk1sign.gyp:pk1sign', 'cmd/pp/pp.gyp:pp', 'cmd/rsaperf/rsaperf.gyp:rsaperf', @@ -195,6 +201,7 @@ 'gtests/mozpkix_gtest/mozpkix_gtest.gyp:mozpkix_gtest', 'gtests/nss_bogo_shim/nss_bogo_shim.gyp:nss_bogo_shim', 'gtests/pk11_gtest/pk11_gtest.gyp:pk11_gtest', + 'gtests/smime_gtest/smime_gtest.gyp:smime_gtest', 'gtests/softoken_gtest/softoken_gtest.gyp:softoken_gtest', 'gtests/ssl_gtest/ssl_gtest.gyp:ssl_gtest', 'gtests/util_gtest/util_gtest.gyp:util_gtest', diff --git a/security/nss/tests/cert/cert.sh b/security/nss/tests/cert/cert.sh index b74de9be53..616043cff1 100644 --- a/security/nss/tests/cert/cert.sh +++ b/security/nss/tests/cert/cert.sh @@ -317,7 +317,7 @@ cert_create_cert() cert_add_cert() { CU_ACTION="Generate Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 if [ "$RET" -ne 0 ]; then return $RET @@ -343,7 +343,7 @@ cert_add_cert() # Generate and add DSA cert # CU_ACTION="Generate DSA Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-dsa@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-dsa@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -k dsa -d "${PROFILEDIR}" -f "${R_PWFILE}" \ -z "${R_NOISE_FILE}" -o req 2>&1 if [ "$RET" -ne 0 ]; then @@ -367,7 +367,7 @@ cert_add_cert() # Generate DSA certificate signed with RSA CU_ACTION="Generate mixed DSA Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-dsamixed@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-dsamixed@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -k dsa -d "${PROFILEDIR}" -f "${R_PWFILE}" \ -z "${R_NOISE_FILE}" -o req 2>&1 if [ "$RET" -ne 0 ]; then @@ -398,7 +398,7 @@ cert_add_cert() # CURVE="secp384r1" CU_ACTION="Generate EC Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ec@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ec@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -k ec -q "${CURVE}" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ -z "${R_NOISE_FILE}" -o req 2>&1 if [ "$RET" -ne 0 ]; then @@ -422,7 +422,7 @@ cert_add_cert() # Generate EC certificate signed with RSA CU_ACTION="Generate mixed EC Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ecmixed@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ecmixed@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -k ec -q "${CURVE}" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ -z "${R_NOISE_FILE}" -o req 2>&1 if [ "$RET" -ne 0 ]; then @@ -455,7 +455,7 @@ cert_add_cert() grep 'TestUser-rsa-pss-interop$' | sed -n 's/^<.*> [^ ]\{1,\} *\([^ ]\{1,\}\).*/\1/p'` CU_ACTION="Generate RSA-PSS Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-rsa-pss@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-rsa-pss@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -k ${KEYID} -f "${R_PWFILE}" \ -z "${R_NOISE_FILE}" -o req 2>&1 @@ -873,15 +873,15 @@ cert_smime_client() ## call to cert_create_cert ends up creating two separate certs ## one for Eve and another for Eve-ec but they both end up with ## the same Subject Alt Name Extension, i.e., both the cert for -## Eve@bogus.com and the cert for Eve-ec@bogus.com end up -## listing eve@bogus.net in the Certificate Subject Alt Name extension. +## Eve@example.com and the cert for Eve-ec@example.com end up +## listing eve@example.net in the Certificate Subject Alt Name extension. ## This can cause a problem later when cmsutil attempts to create ## enveloped data and accidently picks up the ECC cert (NSS currently ## does not support ECC for enveloped data creation). This script ## avoids the problem by ensuring that these conflicting certs are ## never added to the same cert database (see comment marked XXXX). echo "$SCRIPTNAME: Creating multiEmail's Certificate --------------------" - cert_create_cert "${EVEDIR}" "Eve" 60 ${D_EVE} "-7 eve@bogus.net,eve@bogus.cc,beve@bogus.com" + cert_create_cert "${EVEDIR}" "Eve" 60 ${D_EVE} "-7 eve@example.net,eve@example.org,beve@example.com" #echo "************* Copying CA files to ${SERVERDIR}" #cp ${CADIR}/*.db . @@ -891,7 +891,7 @@ cert_smime_client() # #cd ${CERTDIR} #CU_ACTION="Creating ${CERTNAME}'s Server Cert" - #CU_SUBJECT="CN=${CERTNAME}, E=${CERTNAME}@bogus.com, O=BOGUS Netscape, L=Mountain View, ST=California, C=US" + #CU_SUBJECT="CN=${CERTNAME}, E=${CERTNAME}@example.com, O=BOGUS Netscape, L=Mountain View, ST=California, C=US" #certu -S -n "${CERTNAME}" -c "TestCA" -t "u,u,u" -m "$CERTSERIAL" \ # -d ${PROFILEDIR} -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -v 60 2>&1 @@ -975,7 +975,7 @@ cert_extended_ssl() modu -add "RootCerts" -libfile "${ROOTCERTSFILE}" -dbdir "${PROFILEDIR}" 2>&1 CU_ACTION="Generate Cert Request for $CERTNAME (ext)" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request (ext)" @@ -995,7 +995,7 @@ cert_extended_ssl() # Repeat the above for DSA certs # CU_ACTION="Generate DSA Cert Request for $CERTNAME (ext)" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-dsa@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-dsa@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -k dsa -f "${R_PWFILE}" \ -z "${R_NOISE_FILE}" -o req 2>&1 @@ -1017,7 +1017,7 @@ cert_extended_ssl() # Repeat again for mixed DSA certs # CU_ACTION="Generate mixed DSA Cert Request for $CERTNAME (ext)" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-dsamixed@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-dsamixed@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -k dsa -f "${R_PWFILE}" \ -z "${R_NOISE_FILE}" -o req 2>&1 @@ -1040,7 +1040,7 @@ cert_extended_ssl() # EC_CURVE="secp256r1" CU_ACTION="Generate EC Cert Request for $CERTNAME (ext)" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ec@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ec@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -k ec -q "${EC_CURVE}" -f "${R_PWFILE}" \ -z "${R_NOISE_FILE}" -o req 2>&1 @@ -1063,7 +1063,7 @@ cert_extended_ssl() # EC_CURVE="secp256r1" CU_ACTION="Generate mixed EC Cert Request for $CERTNAME (ext)" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ecmixed@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ecmixed@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -k ec -q "${EC_CURVE}" -f "${R_PWFILE}" \ -z "${R_NOISE_FILE}" -o req 2>&1 @@ -1124,7 +1124,7 @@ cert_extended_ssl() modu -add "RootCerts" -libfile "${ROOTCERTSFILE}" -dbdir "${PROFILEDIR}" 2>&1 CU_ACTION="Generate Cert Request for $CERTNAME (ext)" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" \ -o req 2>&1 @@ -1144,7 +1144,7 @@ cert_extended_ssl() # Repeat the above for DSA certs # CU_ACTION="Generate DSA Cert Request for $CERTNAME (ext)" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-dsa@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-dsa@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -k dsa -f "${R_PWFILE}" \ -z "${R_NOISE_FILE}" -o req 2>&1 @@ -1167,7 +1167,7 @@ cert_extended_ssl() # Repeat the above for mixed DSA certs # CU_ACTION="Generate mixed DSA Cert Request for $CERTNAME (ext)" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-dsamixed@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-dsamixed@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -k dsa -f "${R_PWFILE}" \ -z "${R_NOISE_FILE}" -o req 2>&1 @@ -1191,7 +1191,7 @@ cert_extended_ssl() # Repeat the above for EC certs # CU_ACTION="Generate EC Cert Request for $CERTNAME (ext)" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ec@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ec@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -k ec -q "${EC_CURVE}" -f "${R_PWFILE}" \ -z "${R_NOISE_FILE}" -o req 2>&1 @@ -1214,7 +1214,7 @@ cert_extended_ssl() # Repeat the above for mixed EC certs # CU_ACTION="Generate mixed EC Cert Request for $CERTNAME (ext)" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ecmixed@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ecmixed@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -k ec -q "${EC_CURVE}" -f "${R_PWFILE}" \ -z "${R_NOISE_FILE}" -o req 2>&1 @@ -1387,7 +1387,7 @@ MODSCRIPT RETEXPECTED=0 CU_ACTION="Generate Certificate for ${CERTNAME}" - CU_SUBJECT="CN=${CERTNAME}, E=fips@bogus.com, O=BOGUS NSS, OU=FIPS PUB 140, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=${CERTNAME}, E=fips@example.com, O=BOGUS NSS, OU=FIPS PUB 140, L=Mountain View, ST=California, C=US" certu -S -n ${FIPSCERTNICK} -x -t "Cu,Cu,Cu" -d "${PROFILEDIR}" -f "${R_FIPSPWFILE}" -k dsa -v 600 -m 500 -z "${R_NOISE_FILE}" 2>&1 if [ "$RET" -eq 0 ]; then cert_log "SUCCESS: FIPS passed" @@ -1439,7 +1439,7 @@ cert_eccurves() CERTNAME="Curve-${CURVE}" CERTSERIAL=`expr $CERTSERIAL + 1 ` CU_ACTION="Generate EC Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ec@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ec@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -k ec -q "${CURVE}" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ -z "${R_NOISE_FILE}" -o req 2>&1 @@ -1464,7 +1464,7 @@ cert_extensions_test() { COUNT=`expr ${COUNT} + 1` CERTNAME=TestExt${COUNT} - CU_SUBJECT="CN=${CERTNAME}, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=${CERTNAME}, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" echo echo certutil -d ${CERT_EXTENSIONS_DIR} -S -n ${CERTNAME} \ @@ -2026,7 +2026,7 @@ cert_test_password() # finally make sure we can use the old key with the new password CU_ACTION="Generate Certificate for ${CERTNAME} with new password" - CU_SUBJECT="CN=${CERTNAME}, E=password@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=${CERTNAME}, E=password@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -S -n PasswordCert -c PasswordCA -t "u,u,u" -d "${PROFILEDIR}" -f "${R_FIPSPWFILE}" -z "${R_NOISE_FILE}" 2>&1 if [ "$RET" -eq 0 ]; then cert_log "SUCCESS: PASSWORD passed" @@ -2055,7 +2055,7 @@ cert_test_distrust() certu -M -n "Distrusted" -t p,p,p -d ${PROFILEDIR} -f "${R_PWFILE}" 2>&1 echo "$SCRIPTNAME: Creating Distrusted Intermediate" CERTNAME="DistrustedCA" - ALL_CU_SUBJECT="CN=${CERTNAME}, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + ALL_CU_SUBJECT="CN=${CERTNAME}, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" cert_CA ${CADIR} "${CERTNAME}" "-c TestCA" ",," ${D_CA} 2010 2>&1 CU_ACTION="Import Distrusted Intermediate" certu -A -n "${CERTNAME}" -t "p,p,p" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ @@ -2065,7 +2065,7 @@ cert_test_distrust() # since it's not signed by TestCA it requires more steps. CU_ACTION="Generate Cert Request for Leaf Chained to Distrusted CA" CERTNAME="LeafChainedToDistrustedCA" - CU_SUBJECT="CN=${CERTNAME}, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=${CERTNAME}, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request" @@ -2205,7 +2205,7 @@ cert_test_rsapss() CERTNAME="TestUser-rsa-pss1" CU_ACTION="Generate Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request" @@ -2236,7 +2236,7 @@ EOF CERTNAME="TestUser-rsa-pss2" CU_ACTION="Generate Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request" @@ -2267,7 +2267,7 @@ EOF CERTNAME="TestUser-rsa-pss3" CU_ACTION="Generate Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request" @@ -2298,7 +2298,7 @@ EOF CERTNAME="TestUser-rsa-pss4" CU_ACTION="Generate Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" --pss -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request" @@ -2329,7 +2329,7 @@ EOF CERTNAME="TestUser-rsa-pss5" CU_ACTION="Generate Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" --pss -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request" @@ -2360,7 +2360,7 @@ EOF CERTNAME="TestUser-rsa-pss6" CU_ACTION="Generate Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" --pss -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request" @@ -2392,7 +2392,7 @@ EOF CERTNAME="TestUser-rsa-pss7" CU_ACTION="Generate Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" --pss -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request" @@ -2409,7 +2409,7 @@ EOF CERTNAME="TestUser-rsa-pss8" CU_ACTION="Generate Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" --pss -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request" @@ -2440,7 +2440,7 @@ EOF CERTNAME="TestUser-rsa-pss9" CU_ACTION="Generate Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request" @@ -2471,7 +2471,7 @@ EOF CERTNAME="TestUser-rsa-pss10" CU_ACTION="Generate Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request" @@ -2503,7 +2503,7 @@ EOF CERTNAME="TestUser-rsa-pss11" CU_ACTION="Generate Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" --pss -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request" @@ -2571,7 +2571,7 @@ cert_test_rsapss_policy() # Issuer certificate: RSA # Signature: RSA-PSS (explicit, with --pss-sign and -Z SHA1) CU_ACTION="Generate Cert Request for $CERTNAME" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" --pss -o req 2>&1 CU_ACTION="Sign ${CERTNAME}'s Request" diff --git a/security/nss/tests/common/certsetup.sh b/security/nss/tests/common/certsetup.sh index 2b5cef840b..f9ee459e12 100644 --- a/security/nss/tests/common/certsetup.sh +++ b/security/nss/tests/common/certsetup.sh @@ -47,11 +47,12 @@ make_cert() { rsa_ca_rsapss_chain) type_args=(-g 1024 --pss-sign);sign=(-c rsa_ca);type=rsa;; ecdh_rsa) type_args=(-q nistp256);sign=(-c rsa_ca);type=ec ;; esac + msg="create certificate: $@" shift 2 counter=$(($counter + 1)) certscript $@ | ${BINDIR}/certutil -S \ - -z ${R_NOISE_FILE} -d "${PROFILEDIR}" \ + -z "$R_NOISE_FILE" -d "$PROFILEDIR" \ -n $name -s "CN=$name" -t "$trust" "${sign[@]}" -m "$counter" \ -w -2 -v 120 -k "$type" "${type_args[@]}" "${sighash[@]}" -1 -2 - html_msg $? 0 "create certificate: $@" + html_msg $? 0 "$msg" } diff --git a/security/nss/tests/crmf/crmf.sh b/security/nss/tests/crmf/crmf.sh index 6059c19912..4e1f357822 100644 --- a/security/nss/tests/crmf/crmf.sh +++ b/security/nss/tests/crmf/crmf.sh @@ -58,12 +58,12 @@ crmf_init() crmf_main() { echo "$SCRIPTNAME: CRMF/CMMF Tests ------------------------------" - echo "crmftest -d ${P_R_BOBDIR} -p Bob -e dave@bogus.com -s TestCA -P nss crmf decode" - ${BINDIR}/crmftest -d ${P_R_BOBDIR} -p Bob -e dave@bogus.com -s TestCA -P nss crmf decode + echo "crmftest -d ${P_R_BOBDIR} -p Bob -e dave@example.com -s TestCA -P nss crmf decode" + ${BINDIR}/crmftest -d ${P_R_BOBDIR} -p Bob -e dave@example.com -s TestCA -P nss crmf decode html_msg $? 0 "CRMF test" "." - echo "crmftest -d ${P_R_BOBDIR} -p Bob -e dave@bogus.com -s TestCA -P nss cmmf" - ${BINDIR}/crmftest -d ${P_R_BOBDIR} -p Bob -e dave@bogus.com -s TestCA -P nss cmmf + echo "crmftest -d ${P_R_BOBDIR} -p Bob -e dave@example.com -s TestCA -P nss cmmf" + ${BINDIR}/crmftest -d ${P_R_BOBDIR} -p Bob -e dave@example.com -s TestCA -P nss cmmf html_msg $? 0 "CMMF test" "." # Add tests for key recovery and challange as crmftest's capabilities increase diff --git a/security/nss/tests/dbtests/dbtests.sh b/security/nss/tests/dbtests/dbtests.sh index 7b1ee351fd..9dcf738c4c 100644 --- a/security/nss/tests/dbtests/dbtests.sh +++ b/security/nss/tests/dbtests/dbtests.sh @@ -252,7 +252,15 @@ dbtest_main() else html_passed "Nicknane conflict test-setting nickname conflict was correctly rejected" fi - + # import a token private key and make sure the corresponding public key is + # created + ${BINDIR}/pk11importtest -d ${CONFLICT_DIR} -f ${R_PWFILE} + ret=$? + if [ $ret -ne 0 ]; then + html_failed "Importing Token Private Key does not create the corrresponding Public Key" + else + html_passed "Importing Token Private Key correctly creates the corrresponding Public Key" + fi } ################## main ################################################# diff --git a/security/nss/tests/gtests/gtests.sh b/security/nss/tests/gtests/gtests.sh index 583ecec62c..2b45e1ccda 100644 --- a/security/nss/tests/gtests/gtests.sh +++ b/security/nss/tests/gtests/gtests.sh @@ -23,16 +23,22 @@ gtest_init() { cd "$(dirname "$1")" + pwd + SOURCE_DIR="$PWD"/../.. if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then cd ../common . ./init.sh fi SCRIPTNAME=gtests.sh + . "${QADIR}"/common/certsetup.sh if [ -z "${CLEANUP}" ] ; then # if nobody else is responsible for CLEANUP="${SCRIPTNAME}" # cleaning this script will do it fi + + mkdir -p "${GTESTDIR}" + cd "${GTESTDIR}" } ########################## gtest_start ############################# @@ -42,28 +48,32 @@ gtest_start() { echo "gtests: ${GTESTS}" for i in ${GTESTS}; do - if [ ! -f ${BINDIR}/$i ]; then + if [ ! -f "${BINDIR}/$i" ]; then html_unknown "Skipping $i (not built)" continue fi - GTESTDIR="${HOSTDIR}/$i" + DIR="${GTESTDIR}/$i" html_head "$i" - if [ ! -d "$GTESTDIR" ]; then - mkdir -p "$GTESTDIR" + if [ ! -d "$DIR" ]; then + mkdir -p "$DIR" + echo "${BINDIR}/certutil" -N -d "$DIR" --empty-password 2>&1 + "${BINDIR}/certutil" -N -d "$DIR" --empty-password 2>&1 + + PROFILEDIR="$DIR" make_cert dummy p256 sign fi - cd "$GTESTDIR" - GTESTREPORT="$GTESTDIR/report.xml" - PARSED_REPORT="$GTESTDIR/report.parsed" + pushd "$DIR" + GTESTREPORT="$DIR/report.xml" + PARSED_REPORT="$DIR/report.parsed" echo "executing $i" - ${BINDIR}/$i "${SOURCE_DIR}/gtests/freebl_gtest/kat/Hash_DRBG.rsp" \ - -d "$GTESTDIR" --gtest_output=xml:"${GTESTREPORT}" \ - --gtest_filter="${GTESTFILTER-*}" + "${BINDIR}/$i" "${SOURCE_DIR}/gtests/freebl_gtest/kat/Hash_DRBG.rsp" \ + -d "$DIR" -w --gtest_output=xml:"${GTESTREPORT}" \ + --gtest_filter="${GTESTFILTER:-*}" html_msg $? 0 "$i run successfully" echo "test output dir: ${GTESTREPORT}" echo "executing sed to parse the xml report" - sed -f ${COMMON}/parsegtestreport.sed "${GTESTREPORT}" > "${PARSED_REPORT}" + sed -f "${COMMON}/parsegtestreport.sed" "$GTESTREPORT" > "$PARSED_REPORT" echo "processing the parsed report" - cat "${PARSED_REPORT}" | while read result name; do + cat "$PARSED_REPORT" | while read result name; do if [ "$result" = "notrun" ]; then echo "$name" SKIPPED elif [ "$result" = "run" ]; then @@ -72,19 +82,18 @@ gtest_start() html_failed_ignore_core "$name" fi done + popd done } gtest_cleanup() { html "
" - cd ${QADIR} - . common/cleanup.sh + . "${QADIR}"/common/cleanup.sh } ################## main ################################################# -GTESTS="prng_gtest certhigh_gtest certdb_gtest der_gtest pk11_gtest util_gtest freebl_gtest softoken_gtest sysinit_gtest blake2b_gtest" -SOURCE_DIR="$PWD"/../.. -gtest_init $0 +GTESTS="${GTESTS:-prng_gtest certhigh_gtest certdb_gtest der_gtest pk11_gtest util_gtest freebl_gtest softoken_gtest sysinit_gtest blake2b_gtest smime_gtest}" +gtest_init "$0" gtest_start gtest_cleanup diff --git a/security/nss/tests/iopr/cert_iopr.sh b/security/nss/tests/iopr/cert_iopr.sh index bb1bf047c2..b162a2d81c 100644 --- a/security/nss/tests/iopr/cert_iopr.sh +++ b/security/nss/tests/iopr/cert_iopr.sh @@ -252,7 +252,7 @@ download_install_certs() { CERTNAME=$HOSTADDR CU_ACTION="Generate Cert Request for $CERTNAME (ws: $host)" - CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, \ + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, \ L=Mountain View, ST=California, C=US" certu -R -d "${sslServerDir}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}"\ -o $sslServerDir/req 2>&1 diff --git a/security/nss/tests/iopr/server_scr/cert_gen.sh b/security/nss/tests/iopr/server_scr/cert_gen.sh index 17771ade16..6611a0f416 100644 --- a/security/nss/tests/iopr/server_scr/cert_gen.sh +++ b/security/nss/tests/iopr/server_scr/cert_gen.sh @@ -116,7 +116,7 @@ createSignedCert() { echo Creating cert $certName-$keyType with SN=$certSN - CU_SUBJECT="CN=$certName, E=${certName}-${keyType}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=$certName, E=${certName}-${keyType}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" repAndExec \ certutil -R -d $dir -f "${PW_FILE}" -z "${NOISE_FILE}" \ -k $keyType -o $dir/req 2>&1 @@ -267,7 +267,7 @@ generateAndExportCACert() { certName=TestCA [ "$caName" ] && certName=$caName - CU_SUBJECT="CN=NSS IOPR Test CA $$, E=${certName}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + CU_SUBJECT="CN=NSS IOPR Test CA $$, E=${certName}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" repAndExec \ certutil -S -n $certName -t "CTu,CTu,CTu" -v 600 -x -d ${dir} -1 -2 \ -f ${PW_FILE} -z ${NOISE_FILE} -m `expr $$ + 2238` >&1 < TestCA.ca.cert certutil -d . -L -n u50 -r > TestUser50.cert diff --git a/security/nss/tests/libpkix/certs/nss2alice b/security/nss/tests/libpkix/certs/nss2alice index 48172a5ed5..07ebff7ab2 100644 Binary files a/security/nss/tests/libpkix/certs/nss2alice and b/security/nss/tests/libpkix/certs/nss2alice differ diff --git a/security/nss/tests/smime/alice.txt b/security/nss/tests/smime/alice.txt index 0378db464c..7fc52d2558 100644 --- a/security/nss/tests/smime/alice.txt +++ b/security/nss/tests/smime/alice.txt @@ -1,6 +1 @@ -Date: Wed, 20 Sep 2000 00:00:01 -0700 (PDT) -From: alice@bogus.com -Subject: message Alice --> Bob -To: bob@bogus.com - This is a test message from Alice to Bob. diff --git a/security/nss/tests/smime/bob.txt b/security/nss/tests/smime/bob.txt index 330b2c94d5..5ec307f0b6 100644 --- a/security/nss/tests/smime/bob.txt +++ b/security/nss/tests/smime/bob.txt @@ -1,6 +1,6 @@ Date: Wed, 20 Sep 2000 00:00:01 -0700 (PDT) -From: bob@bogus.com +From: bob@example.com Subject: message Bob --> Alice -To: alice@bogus.com +To: alice@example.com This is a test message from Bob to Alice. diff --git a/security/nss/tests/smime/smime.sh b/security/nss/tests/smime/smime.sh index 9cdc0875bd..f319d93ccb 100644 --- a/security/nss/tests/smime/smime.sh +++ b/security/nss/tests/smime/smime.sh @@ -51,12 +51,14 @@ smime_init() mkdir -p ${SMIMEDIR} cd ${SMIMEDIR} cp ${QADIR}/smime/alice.txt ${SMIMEDIR} + + mkdir tb } -smime_sign() +cms_sign() { - HASH_CMD="-H ${HASH}" - SIG=sig.${HASH} + HASH_CMD="-H SHA${HASH}" + SIG=sig.SHA${HASH} echo "$SCRIPTNAME: Signing Detached Message {$HASH} ------------------" echo "cmsutil -S -T -N Alice ${HASH_CMD} -i alice.txt -d ${P_R_ALICEDIR} -p nss -o alice.d${SIG}" @@ -102,23 +104,166 @@ smime_sign() echo "diff alice.txt alice-ec.data.${HASH}" diff alice.txt alice-ec.data.${HASH} html_msg $? 0 "Compare Attached Signed Data and Original (ECDSA w/ ${HASH})" "." - } +header_mime_from_to_subject="MIME-Version: 1.0 +From: Alice@example.com +To: Bob@example.com +Subject: " +header_opaque_signed="Content-Type: application/pkcs7-mime; name=smime.p7m; + smime-type=signed-data +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename=smime.p7m +Content-Description: S/MIME Cryptographic Signature +" + +header_enveloped="Content-Type: application/pkcs7-mime; name=smime.p7m; + smime-type=enveloped-data +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename=smime.p7m +Content-Description: S/MIME Encrypted Message +" + +header_clearsigned="Content-Type: text/plain; charset=utf-8; format=flowed +Content-Transfer-Encoding: quoted-printable +Content-Language: en-US +" + +multipart_start="Content-Type: multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=sha-HASHHASH; boundary=\"------------ms030903020902020502030404\" + +This is a cryptographically signed message in MIME format. + +--------------ms030903020902020502030404" + +multipart_middle=" +--------------ms030903020902020502030404 +Content-Type: application/pkcs7-signature; name=smime.p7s +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename=smime.p7s +Content-Description: S/MIME Cryptographic Signature +" + +multipart_end="--------------ms030903020902020502030404-- +" + +header_plaintext="Content-Type: text/plain +" + +CR=$(printf '\r') + +mime_init() +{ + OUT="tb/alice.mime" + echo "${header_clearsigned}" >>${OUT} + cat alice.txt >>${OUT} + sed -i"" "s/\$/${CR}/" ${OUT} + + OUT="tb/alice.textplain" + echo "${header_plaintext}" >>${OUT} + cat alice.txt >>${OUT} + sed -i"" "s/\$/${CR}/" ${OUT} +} + +smime_enveloped() +{ + ${PROFTOOL} ${BINDIR}/cmsutil -E -r bob@example.com -i tb/alice.mime -d ${P_R_ALICEDIR} -p nss -o tb/alice.mime.env + + OUT="tb/alice.env.eml" + echo -n "${header_mime_from_to_subject}" >>${OUT} + echo "enveloped ${SIG}" >>${OUT} + echo "${header_enveloped}" >>${OUT} + cat "tb/alice.mime.env" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT} + echo >>${OUT} + sed -i"" "s/\$/${CR}/" ${OUT} +} + +smime_signed_enveloped() +{ + SIG=sig.SHA${HASH} + + ${PROFTOOL} ${BINDIR}/cmsutil -S -T -N Alice ${HASH_CMD} -i tb/alice.mime -d ${P_R_ALICEDIR} -p nss -o tb/alice.mime.d${SIG} + + OUT="tb/alice.d${SIG}.multipart" + echo "${multipart_start}" | sed "s/HASHHASH/${HASH}/" >>${OUT} + cat tb/alice.mime | sed 's/\r$//' >>${OUT} + echo "${multipart_middle}" >>${OUT} + cat tb/alice.mime.d${SIG} | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT} + echo "${multipart_end}" >>${OUT} + + ${PROFTOOL} ${BINDIR}/cmsutil -E -r bob@example.com -i ${OUT} -d ${P_R_ALICEDIR} -p nss -o ${OUT}.env + + OUT="tb/alice.d${SIG}.multipart.eml" + echo -n "${header_mime_from_to_subject}" >>${OUT} + echo "clear-signed ${SIG}" >>${OUT} + cat "tb/alice.d${SIG}.multipart" >>${OUT} + sed -i"" "s/\$/$CR/" ${OUT} + + OUT="tb/alice.d${SIG}.multipart.env.eml" + echo -n "${header_mime_from_to_subject}" >>${OUT} + echo "enveloped clear-signed $SIG" >>${OUT} + echo "$header_enveloped" >>${OUT} + cat "tb/alice.d${SIG}.multipart.env" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT} + echo >>${OUT} + sed -i"" "s/\$/$CR/" ${OUT} + + ${PROFTOOL} ${BINDIR}/cmsutil -S -N Alice ${HASH_CMD} -i tb/alice.textplain -d ${P_R_ALICEDIR} -p nss -o tb/alice.textplain.${SIG} + + OUT="tb/alice.${SIG}.opaque" + echo "$header_opaque_signed" >>${OUT} + cat tb/alice.textplain.${SIG} | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT} + + ${PROFTOOL} ${BINDIR}/cmsutil -E -r bob@example.com -i ${OUT} -d ${P_R_ALICEDIR} -p nss -o ${OUT}.env + + OUT="tb/alice.${SIG}.opaque.eml" + echo -n "${header_mime_from_to_subject}" >>${OUT} + echo "opaque-signed $SIG" >>${OUT} + cat "tb/alice.${SIG}.opaque" >>${OUT} + echo >>${OUT} + sed -i"" "s/\$/$CR/" ${OUT} + + OUT="tb/alice.${SIG}.opaque.env.eml" + echo -n "${header_mime_from_to_subject}" >>${OUT} + echo "enveloped opaque-signed $SIG" >>${OUT} + echo "$header_enveloped" >>$OUT + cat "tb/alice.${SIG}.opaque.env" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT} + echo >>${OUT} + sed -i"" "s/\$/$CR/" ${OUT} + + # bad messages below + + OUT="tb/alice.d${SIG}.multipart.bad.eml" + echo -n "${header_mime_from_to_subject}" >>${OUT} + echo "BAD clear-signed $SIG" >>${OUT} + cat "tb/alice.d${SIG}.multipart" | sed 's/test message from Alice/FAKE message NOT from Alice/' >>${OUT} + sed -i"" "s/\$/$CR/" ${OUT} + + OUT="tb/alice.d${SIG}.multipart.mismatch-econtent" + echo "${multipart_start}" | sed "s/HASHHASH/$HASH/" >>${OUT} + cat tb/alice.mime | sed 's/test message from Alice/FAKE message NOT from Alice/' | sed 's/\r$//' >>${OUT} + echo "${multipart_middle}" >>${OUT} + cat tb/alice.textplain.${SIG} | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT} + echo "${multipart_end}" >>${OUT} + + OUT="tb/alice.d${SIG}.multipart.mismatch-econtent.eml" + echo -n "${header_mime_from_to_subject}" >>${OUT} + echo "BAD mismatch-econtent $SIG" >>${OUT} + cat "tb/alice.d${SIG}.multipart.mismatch-econtent" >>${OUT} + sed -i"" "s/\$/$CR/" ${OUT} +} smime_p7() { echo "$SCRIPTNAME: p7 util Data Tests ------------------------------" echo "p7env -d ${P_R_ALICEDIR} -r Alice -i alice.txt -o alice_p7.env" - ${PROFTOOL} ${BINDIR}/p7env -d ${P_R_ALICEDIR} -r Alice -i alice.txt -o alice.env + ${PROFTOOL} ${BINDIR}/p7env -d ${P_R_ALICEDIR} -r Alice -i alice.txt -o alice_p7.env html_msg $? 0 "Creating envelope for user Alice" "." - echo "p7content -d ${P_R_ALICEDIR} -i alice.env -o alice_p7.data" - ${PROFTOOL} ${BINDIR}/p7content -d ${P_R_ALICEDIR} -i alice.env -o alice_p7.data -p nss + echo "p7content -d ${P_R_ALICEDIR} -i alice_p7.env -o alice_p7.data" + ${PROFTOOL} ${BINDIR}/p7content -d ${P_R_ALICEDIR} -i alice_p7.env -o alice_p7.data -p nss html_msg $? 0 "Verifying file delivered to user Alice" "." - sed -e '3,8p' -n alice_p7.data > alice_p7.data.sed + sed -e '3,3p' -n alice_p7.data > alice_p7.data.sed echo "diff alice.txt alice_p7.data.sed" diff alice.txt alice_p7.data.sed @@ -139,20 +284,26 @@ smime_p7() ######################################################################## smime_main() { + mime_init + smime_enveloped - HASH=SHA1 - smime_sign - HASH=SHA256 - smime_sign - HASH=SHA384 - smime_sign - HASH=SHA512 - smime_sign + HASH="1" + cms_sign + smime_signed_enveloped + HASH="256" + cms_sign + smime_signed_enveloped + HASH="384" + cms_sign + smime_signed_enveloped + HASH="512" + cms_sign + smime_signed_enveloped echo "$SCRIPTNAME: Enveloped Data Tests ------------------------------" - echo "cmsutil -E -r bob@bogus.com -i alice.txt -d ${P_R_ALICEDIR} -p nss \\" + echo "cmsutil -E -r bob@example.com -i alice.txt -d ${P_R_ALICEDIR} -p nss \\" echo " -o alice.env" - ${PROFTOOL} ${BINDIR}/cmsutil -E -r bob@bogus.com -i alice.txt -d ${P_R_ALICEDIR} -p nss -o alice.env + ${PROFTOOL} ${BINDIR}/cmsutil -E -r bob@example.com -i alice.txt -d ${P_R_ALICEDIR} -p nss -o alice.env html_msg $? 0 "Create Enveloped Data Alice" "." echo "cmsutil -D -i alice.env -d ${P_R_BOBDIR} -p nss -o alice.data1" @@ -166,23 +317,23 @@ smime_main() # multiple recip echo "$SCRIPTNAME: Testing multiple recipients ------------------------------" echo "cmsutil -E -i alice.txt -d ${P_R_ALICEDIR} -o alicecc.env \\" - echo " -r bob@bogus.com,dave@bogus.com" + echo " -r bob@example.com,dave@example.com" ${PROFTOOL} ${BINDIR}/cmsutil -E -i alice.txt -d ${P_R_ALICEDIR} -o alicecc.env \ - -r bob@bogus.com,dave@bogus.com + -r bob@example.com,dave@example.com ret=$? html_msg $ret 0 "Create Multiple Recipients Enveloped Data Alice" "." if [ $ret != 0 ] ; then echo "certutil -L -d ${P_R_ALICEDIR}" ${BINDIR}/certutil -L -d ${P_R_ALICEDIR} - echo "certutil -L -d ${P_R_ALICEDIR} -n dave@bogus.com" - ${BINDIR}/certutil -L -d ${P_R_ALICEDIR} -n dave@bogus.com + echo "certutil -L -d ${P_R_ALICEDIR} -n dave@example.com" + ${BINDIR}/certutil -L -d ${P_R_ALICEDIR} -n dave@example.com fi echo "$SCRIPTNAME: Testing multiple email addrs ------------------------------" echo "cmsutil -E -i alice.txt -d ${P_R_ALICEDIR} -o aliceve.env \\" - echo " -r eve@bogus.net" + echo " -r eve@example.net" ${PROFTOOL} ${BINDIR}/cmsutil -E -i alice.txt -d ${P_R_ALICEDIR} -o aliceve.env \ - -r eve@bogus.net + -r eve@example.net ret=$? html_msg $ret 0 "Encrypt to a Multiple Email cert" "." @@ -208,9 +359,9 @@ smime_main() html_msg $? 0 "Compare Decoded with Multiple Email cert" "." echo "$SCRIPTNAME: Sending CERTS-ONLY Message ------------------------------" - echo "cmsutil -O -r \"Alice,bob@bogus.com,dave@bogus.com\" \\" + echo "cmsutil -O -r \"Alice,bob@example.com,dave@example.com\" \\" echo " -d ${P_R_ALICEDIR} > co.der" - ${PROFTOOL} ${BINDIR}/cmsutil -O -r "Alice,bob@bogus.com,dave@bogus.com" -d ${P_R_ALICEDIR} > co.der + ${PROFTOOL} ${BINDIR}/cmsutil -O -r "Alice,bob@example.com,dave@example.com" -d ${P_R_ALICEDIR} > co.der html_msg $? 0 "Create Certs-Only Alice" "." echo "cmsutil -D -i co.der -d ${P_R_BOBDIR}" @@ -219,9 +370,9 @@ smime_main() echo "$SCRIPTNAME: Encrypted-Data Message ---------------------------------" echo "cmsutil -C -i alice.txt -e alicehello.env -d ${P_R_ALICEDIR} \\" - echo " -r \"bob@bogus.com\" > alice.enc" + echo " -r \"bob@example.com\" > alice.enc" ${PROFTOOL} ${BINDIR}/cmsutil -C -i alice.txt -e alicehello.env -d ${P_R_ALICEDIR} \ - -r "bob@bogus.com" > alice.enc + -r "bob@example.com" > alice.enc html_msg $? 0 "Create Encrypted-Data" "." echo "cmsutil -D -i alice.enc -d ${P_R_BOBDIR} -e alicehello.env -p nss \\" @@ -232,6 +383,16 @@ smime_main() diff alice.txt alice.data2 html_msg $? 0 "Compare Decoded and Original Data" "." } + +smime_data_tb() +{ + ${BINDIR}/pk12util -d ${P_R_ALICEDIR} -o tb/Alice.p12 -n Alice -K nss -W "" + ${BINDIR}/pk12util -d ${P_R_BOBDIR} -o tb/Bob.p12 -n Bob -K nss -W "" + ${BINDIR}/pk12util -d ${P_R_DAVEDIR} -o tb/Dave.p12 -n Dave -K nss -W "" + ${BINDIR}/pk12util -d ${P_R_EVEDIR} -o tb/Eve.p12 -n Eve -K nss -W "" + CAOUT=tb/TestCA.pem + cat ${P_R_CADIR}/TestCA.ca.cert | sed 's/\r$//' | ${BINDIR}/btoa -w c >> ${CAOUT} +} ############################## smime_cleanup ########################### # local shell function to finish this script (no exit since it might be @@ -248,6 +409,7 @@ smime_cleanup() smime_init smime_main +smime_data_tb smime_p7 smime_cleanup diff --git a/security/nss/tests/ssl/ssl.sh b/security/nss/tests/ssl/ssl.sh index c1730d8d76..525855e100 100644 --- a/security/nss/tests/ssl/ssl.sh +++ b/security/nss/tests/ssl/ssl.sh @@ -1225,6 +1225,51 @@ ssl_scheme() html "
" } +############################ ssl_scheme_stress ########################## +# local shell function to test strsclnt and selfserv handling of signature schemes +######################################################################### +ssl_scheme_stress() +{ + if [ "$SERVER_MODE" = "fips" -o "$CLIENT_MODE" = "fips" ] ; then + echo "$SCRIPTNAME: skipping $testname (non-FIPS only)" + return 0 + fi + + html_head "SSL SCHEME $NORM_EXT - server $SERVER_MODE/client $CLIENT_MODE" + + NO_ECC_CERTS=1 + schemes=("rsa_pkcs1_sha256" "rsa_pss_rsae_sha256" "rsa_pkcs1_sha256,rsa_pss_rsae_sha256") + for sscheme in "${schemes[@]}"; do + for cscheme in "${schemes[@]}"; do + testname="ssl_scheme server='$sscheme' client='$cscheme'" + echo "${testname}" + + start_selfserv -V tls1.2:tls1.2 -J "$sscheme" + + echo "strsclnt -q -p ${PORT} -d ${P_R_CLIENTDIR} $verbose ${CLIENT_OPTIONS} \\" + echo " -V tls1.2:tls1.2 -J "$cscheme" ${HOSTADDR} < ${REQUEST_FILE}" + ${PROFTOOL} ${BINDIR}/strsclnt -q -p ${PORT} ${CLIENT_OPTIONS} \ + -d ${P_R_CLIENTDIR} $verbose -V tls1.2:tls1.2 -J "$cscheme" ${HOSTADDR} < ${REQUEST_FILE} 2>&1 + ret=$? + # If both schemes include just one option and those options don't + # match, then the test should fail; otherwise, assume that it works. + if [ "${cscheme#*,}" = "$cscheme" -a \ + "${sscheme#*,}" = "$sscheme" -a \ + "$cscheme" != "$sscheme" ]; then + expected=1 + else + expected=0 + fi + html_msg $ret $expected "${testname}" \ + "produced a returncode of $ret, expected is $expected" + kill_selfserv + done + done + NO_ECC_CERTS=0 + + html "
" +} + ############################## ssl_cleanup ############################# # local shell function to finish this script (no exit since it might be # sourced) @@ -1267,6 +1312,7 @@ ssl_run() ;; "scheme") ssl_scheme + ssl_scheme_stress ;; esac done diff --git a/security/nss/tests/ssl/sslpolicy.txt b/security/nss/tests/ssl/sslpolicy.txt index 82c15d2afa..844fd0e8f5 100644 --- a/security/nss/tests/ssl/sslpolicy.txt +++ b/security/nss/tests/ssl/sslpolicy.txt @@ -74,6 +74,8 @@ # SECT409R1 # SECT571K1 # SECT571R1 +# Signatures: +# DSA # Hashes: # MD2 # MD4 @@ -172,3 +174,4 @@ 1 noECC SSL3 d allow=tls-version-min=tls1.0:tls-version-max=tls1.2 Disallow Version Exlicitly 1 noECC SSL3 d disallow=all_allow=hmac-sha1:sha256:rsa:des-ede3-cbc:tls-version-min=tls1.0:tls-version-max=tls1.2 Disallow Version Implicitly Narrow. 1 noECC SSL3 d disallow=all_allow=md2/all:md4/all:md5/all:sha1/all:sha256/all:sha384/all:sha512/all:hmac-sha1/all:hmac-sha224/all:hmac-sha256/all:hmac-sha384/all:hmac-sha512/all:hmac-md5/all:camellia128-cbc/all:camellia192-cbc/all:camellia256-cbc/all:seed-cbc/all:des-ede3-cbc/all:des-40-cbc/all:des-cbc/all:null-cipher/all:rc2/all:rc4/all:idea/all:rsa/all:rsa-export/all:dhe-rsa/all:dhe-dss/all:ecdhe-ecdsa/all:ecdhe-rsa/all:ecdh-ecdsa/all:ecdh-rsa/all:tls-version-min=tls1.0:tls-version-max=tls1.2 Disallow Version Implicitly. + 0 noECC SSL3 d disallow=dsa Disallow DSA Signatures Explicitly.