Bug 1296266 - NSS 3.27 tip d9f7136f2ae3, r=ttaubert

--HG--
extra : rebase_source : 81827c237adce9e4ae6128ce9200344a228a817b
This commit is contained in:
Franziskus Kiefer 2016-09-16 10:00:57 -07:00
Родитель f34c930bf6
Коммит a50cf23e57
106 изменённых файлов: 2656 добавлений и 2425 удалений

Просмотреть файл

@ -251,3 +251,6 @@ toolkit/webapps/**
# Third party
toolkit/modules/third_party/**
#NSS
security/nss/**

Просмотреть файл

@ -77,14 +77,8 @@ tasks:
bin/checkout.sh &&
nss/automation/taskcluster/scripts/extend_task_graph.sh
artifacts:
public:
type: "directory"
path: "/home/worker/artifacts"
expires: "{{#from_now}}7 days{{/from_now}}"
graphs:
- /home/worker/artifacts/graph.json
features:
taskclusterProxy: true
extra:
treeherder:

Просмотреть файл

@ -1 +1 @@
NSS_3_27_BETA3
NSS_3_27_BRANCH

Просмотреть файл

@ -44,8 +44,8 @@ apt-get install -y --no-install-recommends ${apt_packages[@]}
# 32-bit builds
ln -s /usr/include/x86_64-linux-gnu/zconf.h /usr/include
# Install clang-3.8 into /usr/local/.
curl http://llvm.org/releases/3.8.0/clang+llvm-3.8.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz | tar xJv -C /usr/local --strip-components=1
# Install clang-3.9 into /usr/local/.
curl http://llvm.org/releases/3.9.0/clang+llvm-3.9.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz | tar xJv -C /usr/local --strip-components=1
# Compiler options.
update-alternatives --install /usr/bin/gcc gcc /usr/local/bin/clang 5

Просмотреть файл

@ -1,40 +0,0 @@
---
reruns: 2
task:
created: !from_now 0
deadline: !from_now 24
provisionerId: localprovisioner
workerType: nss-rpi
schedulerId: task-graph-scheduler
metadata:
owner: !env TC_OWNER
source: !env TC_SOURCE
payload:
maxRunTime: 7200
image: ttaubert/nss-rpi-ci:0.0.3
artifacts:
public:
type: directory
path: /home/worker/artifacts
expires: !from_now 24
command:
- "/bin/bash"
- "-c"
- "bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh"
env:
NSS_HEAD_REPOSITORY: !env NSS_HEAD_REPOSITORY
NSS_HEAD_REVISION: !env NSS_HEAD_REVISION
GCC_VERSION: gcc-5
GXX_VERSION: g++-5
extra:
treeherder:
tier: 3 # hide jobs by default
jobKind: build
symbol: B

Просмотреть файл

@ -1,27 +0,0 @@
---
reruns: 2
task:
created: !from_now 0
deadline: !from_now 24
provisionerId: localprovisioner
workerType: nss-rpi
schedulerId: task-graph-scheduler
metadata:
owner: !env TC_OWNER
source: !env TC_SOURCE
payload:
maxRunTime: 7200
image: ttaubert/nss-rpi-ci:0.0.3
command:
- "/bin/bash"
- "-c"
- "bin/checkout.sh && nss/automation/taskcluster/scripts/run_tests.sh"
extra:
treeherder:
tier: 3 # hide jobs by default
jobKind: test

Просмотреть файл

@ -1,29 +0,0 @@
---
- task:
metadata:
name: "Linux 32 (ARM, debug)"
description: "Linux 32 (ARM, debug)"
extra:
treeherder:
build:
platform: linux32
machine:
platform: linux32
collection:
arm-debug: true
tests:
- chains
- cipher
- crmf
- db
- ec
- fips
- gtests
- lowhash
- merge
- sdr
- smime
- ssl
- tools

Просмотреть файл

@ -1,147 +0,0 @@
/* 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/. */
var fs = require("fs");
var path = require("path");
var merge = require("merge");
var slugid = require("slugid");
var flatmap = require("flatmap");
var yaml = require("./yaml");
var try_syntax = require("./try_syntax");
var image_builder = require("./image_builder");
// Default values for debugging.
var TC_OWNER = process.env.TC_OWNER || "{{tc_owner}}";
var TC_SOURCE = process.env.TC_SOURCE || "{{tc_source}}";
var TC_PROJECT = process.env.TC_PROJECT || "{{tc_project}}";
var TC_COMMENT = process.env.TC_COMMENT || "{{tc_comment}}";
var NSS_PUSHLOG_ID = process.env.NSS_PUSHLOG_ID || "{{nss_pushlog_id}}";
var NSS_HEAD_REVISION = process.env.NSS_HEAD_REVISION || "{{nss_head_rev}}";
// Add base information to the given task.
function decorateTask(task) {
// Assign random task id.
task.taskId = slugid.v4();
// TreeHerder routes.
task.task.routes = [
"tc-treeherder-stage.v2." + TC_PROJECT + "." + NSS_HEAD_REVISION + "." + NSS_PUSHLOG_ID,
"tc-treeherder.v2." + TC_PROJECT + "." + NSS_HEAD_REVISION + "." + NSS_PUSHLOG_ID
];
}
// Generate all tasks for a given build.
function generateBuildTasks(platform, file) {
var dir = path.join(__dirname, "./" + platform);
// Parse base definitions.
var buildBase = yaml.parse(path.join(dir, "_build_base.yml"), {});
var testBase = yaml.parse(path.join(dir, "_test_base.yml"), {});
return flatmap(yaml.parse(path.join(dir, file)), function (task) {
// Merge base build task definition with the current one.
var tasks = [task = merge.recursive(true, buildBase, task)];
// Add base info.
decorateTask(task);
// Generate test tasks.
if (task.tests) {
// The base definition for all tests of this platform.
var base = merge.recursive(true, {
requires: [task.taskId],
task: {
payload: {
env: {
TC_PARENT_TASK_ID: task.taskId
}
}
}
}, testBase);
// Generate and append test task definitions.
tasks = tasks.concat(flatmap(task.tests, function (name) {
return generateTestTasks(name, base, task);
}));
// |tests| is not part of the schema.
delete task.tests;
}
return tasks;
});
}
// Generate all tasks for a given test.
function generateTestTasks(name, base, task) {
// Load test definitions.
var dir = path.join(__dirname, "./tests");
var tests = yaml.parse(path.join(dir, name + ".yml"));
return tests.map(function (test) {
// Merge test with base definition.
test = merge.recursive(true, base, test);
// Add base info.
decorateTask(test);
// We only want to carry over environment variables...
test.task.payload.env =
merge.recursive(true, task.task.payload.env,
test.task.payload.env);
// ...and TreeHerder configuration data.
test.task.extra.treeherder =
merge.recursive(true, task.task.extra.treeherder,
test.task.extra.treeherder);
return test;
});
}
// Generate all tasks for a given platform.
function generatePlatformTasks(platform) {
var dir = path.join(__dirname, "./" + platform);
var buildBase = yaml.parse(path.join(dir, "_build_base.yml"), {});
var testBase = yaml.parse(path.join(dir, "_test_base.yml"), {});
// Parse all build tasks.
return flatmap(fs.readdirSync(dir), function (file) {
if (!file.startsWith("_") && file.endsWith(".yml")) {
var tasks = generateBuildTasks(platform, file);
// Convert env variables to strings.
tasks.forEach(function (task) {
var env = task.task.payload.env || {};
Object.keys(env).forEach(function (name) {
if (typeof(env[name]) != "undefined") {
env[name] = env[name] + "";
}
});
});
return tasks;
}
});
}
// Construct the task graph.
var graph = {
tasks: flatmap(["linux", "windows", "arm", "tools"], generatePlatformTasks)
};
// Filter tasks when try syntax is given.
if (TC_PROJECT == "nss-try") {
graph.tasks = try_syntax.filterTasks(graph.tasks, TC_COMMENT);
}
// Inject the image builder tasks and dependencies.
image_builder.asyncTweakTasks(graph.tasks).then(function (tasks) {
graph.tasks = tasks;
// Output the final graph.
process.stdout.write(JSON.stringify(graph, null, 2));
});

Просмотреть файл

@ -1,148 +0,0 @@
/* 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/. */
var fs = require("fs");
var path = require("path");
var crypto = require("crypto");
var slugid = require("slugid");
var flatmap = require("flatmap");
var taskcluster = require("taskcluster-client");
var yaml = require("./yaml");
// Default values for debugging.
var TC_PROJECT = process.env.TC_PROJECT || "{{tc_project}}";
var NSS_PUSHLOG_ID = process.env.NSS_PUSHLOG_ID || "{{nss_pushlog_id}}";
var NSS_HEAD_REVISION = process.env.NSS_HEAD_REVISION || "{{nss_head_rev}}";
// Add base information to the given task.
function decorateTask(task) {
// Assign random task id.
task.taskId = slugid.v4();
// TreeHerder routes.
task.task.routes = [
"tc-treeherder-stage.v2." + TC_PROJECT + "." + NSS_HEAD_REVISION + "." + NSS_PUSHLOG_ID,
"tc-treeherder.v2." + TC_PROJECT + "." + NSS_HEAD_REVISION + "." + NSS_PUSHLOG_ID
];
}
// Compute the SHA-256 digest.
function sha256(data) {
var hash = crypto.createHash("sha256");
hash.update(data);
return hash.digest("hex");
}
// Recursively collect a list of all files of a given directory.
function collectFilesInDirectory(dir) {
return flatmap(fs.readdirSync(dir), function (entry) {
var entry_path = path.join(dir, entry);
if (fs.lstatSync(entry_path).isDirectory()) {
return collectFilesInDirectory(entry_path);
}
return [entry_path];
});
}
// Compute a context hash for the given context path.
function computeContextHash(context_path) {
var root = path.join(__dirname, "../../..");
var dir = path.join(root, context_path);
var files = collectFilesInDirectory(dir).sort();
var hashes = files.map(function (file) {
return sha256(file + "|" + fs.readFileSync(file, "utf-8"));
});
return sha256(hashes.join(","));
}
// Generates the image-builder task description.
function generateImageBuilderTask(context_path) {
var task = yaml.parse(path.join(__dirname, "image_builder.yml"), {});
// Add base info.
decorateTask(task);
// Add info for docker image building.
task.task.payload.env.CONTEXT_PATH = context_path;
task.task.payload.env.HASH = computeContextHash(context_path);
return task;
}
// Returns a Promise<bool> that tells whether the task with the given id
// has a public/image.tar artifact with a ready-to-use docker image.
function asyncTaskHasImageArtifact(taskId) {
var queue = new taskcluster.Queue();
return queue.listLatestArtifacts(taskId).then(function (result) {
return result.artifacts.some(function (artifact) {
return artifact.name == "public/image.tar";
});
}, function () {
return false;
});
}
// Returns a Promise<task-id|null> with either a task id or null, depending
// on whether we could find a task in the given namespace with a docker image.
function asyncFindTaskWithImageArtifact(ns) {
var index = new taskcluster.Index();
return index.findTask(ns).then(function (result) {
return asyncTaskHasImageArtifact(result.taskId).then(function (has_image) {
return has_image ? result.taskId : null;
});
}, function () {
return null;
});
}
// Tweak the given list of tasks by injecting the image-builder task
// and setting the right dependencies where needed.
function asyncTweakTasks(tasks) {
var id = "linux";
var cx_path = "automation/taskcluster/docker";
var hash = computeContextHash(cx_path);
var ns = "docker.images.v1." + TC_PROJECT + "." + id + ".hash." + hash;
var additional_tasks = [];
// Check whether the docker image was already built.
return asyncFindTaskWithImageArtifact(ns).then(function (taskId) {
var builder_task;
if (!taskId) {
// No docker image found, add a task to build one.
builder_task = generateImageBuilderTask(cx_path);
taskId = builder_task.taskId;
// Add a route so we can find the task later again.
builder_task.task.routes.push("index." + ns);
additional_tasks.push(builder_task);
}
tasks.forEach(function (task) {
if (task.task.payload.image == cx_path) {
task.task.payload.image = {
path: "public/image.tar",
type: "task-image",
taskId: taskId
};
// Add a dependency only for top-level tasks (builds & tools) and only
// if we added an image building task. Otherwise we don't need to wait.
if (builder_task && !task.requires) {
task.requires = [taskId];
}
}
});
return additional_tasks.concat(tasks);
});
}
module.exports.asyncTweakTasks = asyncTweakTasks;

Просмотреть файл

@ -1,49 +0,0 @@
---
reruns: 2
task:
created: !from_now 0
deadline: !from_now 24
provisionerId: aws-provisioner-v1
workerType: hg-worker
schedulerId: task-graph-scheduler
metadata:
name: Image Builder
description: Image Builder
owner: !env TC_OWNER
source: !env TC_SOURCE
payload:
maxRunTime: 3600
image: taskcluster/image_builder:0.1.5
artifacts:
public/image.tar:
type: file
path: /artifacts/image.tar
expires: !from_now 8760
command:
- "/bin/bash"
- "-c"
- "/home/worker/bin/build_image.sh"
env:
HEAD_REPOSITORY: !env NSS_HEAD_REPOSITORY
BASE_REPOSITORY: !env NSS_HEAD_REPOSITORY
HEAD_REV: !env NSS_HEAD_REVISION
HEAD_REF: !env NSS_HEAD_REVISION
PROJECT: !env TC_PROJECT
features:
dind: true
extra:
treeherder:
build:
platform: nss-decision
machine:
platform: nss-decision
jobKind: build
symbol: I

Просмотреть файл

@ -1,39 +0,0 @@
---
reruns: 2
task:
created: !from_now 0
deadline: !from_now 24
provisionerId: aws-provisioner-v1
workerType: hg-worker
schedulerId: task-graph-scheduler
metadata:
owner: !env TC_OWNER
source: !env TC_SOURCE
payload:
maxRunTime: 3600
image: automation/taskcluster/docker
artifacts:
public:
type: directory
path: /home/worker/artifacts
expires: !from_now 24
command:
- "/bin/bash"
- "-c"
- "bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh"
env:
NSS_HEAD_REPOSITORY: !env NSS_HEAD_REPOSITORY
NSS_HEAD_REVISION: !env NSS_HEAD_REVISION
GCC_VERSION: gcc-5
GXX_VERSION: g++-5
extra:
treeherder:
jobKind: build
symbol: B

Просмотреть файл

@ -1,26 +0,0 @@
---
reruns: 2
task:
created: !from_now 0
deadline: !from_now 24
provisionerId: aws-provisioner-v1
workerType: hg-worker
schedulerId: task-graph-scheduler
metadata:
owner: !env TC_OWNER
source: !env TC_SOURCE
payload:
maxRunTime: 3600
image: automation/taskcluster/docker
command:
- "/bin/bash"
- "-c"
- "bin/checkout.sh && nss/automation/taskcluster/scripts/run_tests.sh"
extra:
treeherder:
jobKind: test

Просмотреть файл

@ -1,116 +0,0 @@
---
- task:
metadata:
name: "Linux 32 (debug)"
description: "Linux 32 (debug)"
extra:
treeherder:
build:
platform: linux32
machine:
platform: linux32
collection:
debug: true
tests:
- chains
- cipher
- crmf
- db
- ec
- fips
- gtests
- lowhash
- merge
- sdr
- smime
- ssl
- tools
- task:
metadata:
name: "Linux 32 (debug, clang-3.8)"
description: "Linux 32 (debug, clang-3.8)"
payload:
env:
GCC_VERSION: clang
GXX_VERSION: clang++
extra:
treeherder:
build:
platform: linux32
machine:
platform: linux32
collection:
debug: true
groupSymbol: Builds
groupName: Various builds
symbol: clang-3.8
- task:
metadata:
name: "Linux 32 (debug, gcc-4.8)"
description: "Linux 32 (debug, gcc-4.8)"
payload:
env:
GCC_VERSION: gcc-4.8
GXX_VERSION: g++-4.8
extra:
treeherder:
build:
platform: linux32
machine:
platform: linux32
collection:
debug: true
groupSymbol: Builds
groupName: Various builds
symbol: gcc-4.8
- task:
metadata:
name: "Linux 32 (debug, gcc-6.1)"
description: "Linux 32 (debug, gcc-6.1)"
payload:
env:
GCC_VERSION: gcc-6
GXX_VERSION: g++-6
extra:
treeherder:
build:
platform: linux32
machine:
platform: linux32
collection:
debug: true
groupSymbol: Builds
groupName: Various builds
symbol: gcc-6.1
- task:
metadata:
name: "Linux 32 (debug, NSS_NO_PKCS11_BYPASS=1)"
description: "Linux 32 (debug, NSS_NO_PKCS11_BYPASS=1)"
payload:
env:
NSS_NO_PKCS11_BYPASS: 1
extra:
treeherder:
build:
platform: linux32
machine:
platform: linux32
collection:
debug: true
groupSymbol: Builds
groupName: Various builds
symbol: noPkcs11Bypass

Просмотреть файл

@ -1,124 +0,0 @@
---
- task:
metadata:
name: "Linux 32 (opt)"
description: "Linux 32 (opt)"
payload:
env:
BUILD_OPT: 1
extra:
treeherder:
build:
platform: linux32
machine:
platform: linux32
collection:
opt: true
tests:
- chains
- cipher
- crmf
- db
- ec
- fips
- gtests
- lowhash
- merge
- sdr
- smime
- ssl
- tools
- task:
metadata:
name: "Linux 32 (opt, clang-3.8)"
description: "Linux 32 (opt, clang-3.8)"
payload:
env:
GCC_VERSION: clang
GXX_VERSION: clang++
BUILD_OPT: 1
extra:
treeherder:
build:
platform: linux32
machine:
platform: linux32
collection:
opt: true
groupSymbol: Builds
groupName: Various builds
symbol: clang-3.8
- task:
metadata:
name: "Linux 32 (opt, gcc-4.8)"
description: "Linux 32 (opt, gcc-4.8)"
payload:
env:
GCC_VERSION: gcc-4.8
GXX_VERSION: g++-4.8
BUILD_OPT: 1
extra:
treeherder:
build:
platform: linux32
machine:
platform: linux32
collection:
opt: true
groupSymbol: Builds
groupName: Various builds
symbol: gcc-4.8
- task:
metadata:
name: "Linux 32 (opt, gcc-6.1)"
description: "Linux 32 (opt, gcc-6.1)"
payload:
env:
GCC_VERSION: gcc-6
GXX_VERSION: g++-6
BUILD_OPT: 1
extra:
treeherder:
build:
platform: linux32
machine:
platform: linux32
collection:
opt: true
groupSymbol: Builds
groupName: Various builds
symbol: gcc-6.1
- task:
metadata:
name: "Linux 32 (opt, NSS_NO_PKCS11_BYPASS=1)"
description: "Linux 32 (opt, NSS_NO_PKCS11_BYPASS=1)"
payload:
env:
NSS_NO_PKCS11_BYPASS: 1
BUILD_OPT: 1
extra:
treeherder:
build:
platform: linux32
machine:
platform: linux32
collection:
opt: true
groupSymbol: Builds
groupName: Various builds
symbol: noPkcs11Bypass

Просмотреть файл

@ -1,38 +0,0 @@
---
- task:
metadata:
name: "Linux 64 (ASan, debug)"
description: "Linux 64 (ASan, debug)"
payload:
env:
GCC_VERSION: clang
GXX_VERSION: clang++
NSS_DISABLE_ARENA_FREE_LIST: 1
NSS_DISABLE_UNLOAD: 1
USE_ASAN: 1
USE_64: 1
extra:
treeherder:
build:
platform: linux64
machine:
platform: linux64
collection:
asan: true
tests:
- chains
- cipher
- crmf
- db
- ec
- fips
- gtests
- lowhash
- merge
- sdr
- smime
- ssl
- tools

Просмотреть файл

@ -1,146 +0,0 @@
---
- task:
metadata:
name: "Linux 64 (debug)"
description: "Linux 64 (debug)"
payload:
env:
USE_64: 1
extra:
treeherder:
build:
platform: linux64
machine:
platform: linux64
collection:
debug: true
tests:
- chains
- cipher
- crmf
- db
- ec
- fips
- gtests
- lowhash
- merge
- sdr
- smime
- ssl
- tools
- task:
metadata:
name: "Linux 64 (debug, clang-3.8)"
description: "Linux 64 (debug, clang-3.8)"
payload:
env:
GCC_VERSION: clang
GXX_VERSION: clang++
USE_64: 1
extra:
treeherder:
build:
platform: linux64
machine:
platform: linux64
collection:
debug: true
groupSymbol: Builds
groupName: Various builds
symbol: clang-3.8
- task:
metadata:
name: "Linux 64 (debug, gcc-4.8)"
description: "Linux 64 (debug, gcc-4.8)"
payload:
env:
GCC_VERSION: gcc-4.8
GXX_VERSION: g++-4.8
USE_64: 1
extra:
treeherder:
build:
platform: linux64
machine:
platform: linux64
collection:
debug: true
groupSymbol: Builds
groupName: Various builds
symbol: gcc-4.8
- task:
metadata:
name: "Linux 64 (debug, gcc-6.1)"
description: "Linux 64 (debug, gcc-6.1)"
payload:
env:
GCC_VERSION: gcc-6
GXX_VERSION: g++-6
USE_64: 1
extra:
treeherder:
build:
platform: linux64
machine:
platform: linux64
collection:
debug: true
groupSymbol: Builds
groupName: Various builds
symbol: gcc-6.1
- task:
metadata:
name: "Linux 64 (debug, NSS_NO_PKCS11_BYPASS=1)"
description: "Linux 64 (debug, NSS_NO_PKCS11_BYPASS=1)"
payload:
env:
NSS_NO_PKCS11_BYPASS: 1
USE_64: 1
extra:
treeherder:
build:
platform: linux64
machine:
platform: linux64
collection:
debug: true
groupSymbol: Builds
groupName: Various builds
symbol: noPkcs11Bypass
- task:
metadata:
name: "Linux 64 (debug, NSS_DISABLE_LIBPKIX=1)"
description: "Linux 64 (debug, NSS_DISABLE_LIBPKIX=1)"
payload:
env:
NSS_DISABLE_LIBPKIX: 1
USE_64: 1
extra:
treeherder:
build:
platform: linux64
machine:
platform: linux64
collection:
debug: true
groupSymbol: Builds
groupName: Various builds
symbol: noLibpkix

Просмотреть файл

@ -1,129 +0,0 @@
---
- task:
metadata:
name: "Linux 64 (opt)"
description: "Linux 64 (opt)"
payload:
env:
BUILD_OPT: 1
USE_64: 1
extra:
treeherder:
build:
platform: linux64
machine:
platform: linux64
collection:
opt: true
tests:
- chains
- cipher
- crmf
- db
- ec
- fips
- gtests
- lowhash
- merge
- sdr
- smime
- ssl
- tools
- task:
metadata:
name: "Linux 64 (opt, clang-3.8)"
description: "Linux 64 (opt, clang-3.8)"
payload:
env:
GCC_VERSION: clang
GXX_VERSION: clang++
BUILD_OPT: 1
USE_64: 1
extra:
treeherder:
build:
platform: linux64
machine:
platform: linux64
collection:
opt: true
groupSymbol: Builds
groupName: Various builds
symbol: clang-3.8
- task:
metadata:
name: "Linux 64 (opt, gcc-4.8)"
description: "Linux 64 (opt, gcc-4.8)"
payload:
env:
GCC_VERSION: gcc-4.8
GXX_VERSION: g++-4.8
BUILD_OPT: 1
USE_64: 1
extra:
treeherder:
build:
platform: linux64
machine:
platform: linux64
collection:
opt: true
groupSymbol: Builds
groupName: Various builds
symbol: gcc-4.8
- task:
metadata:
name: "Linux 64 (opt, gcc-6.1)"
description: "Linux 64 (opt, gcc-6.1)"
payload:
env:
GCC_VERSION: gcc-6
GXX_VERSION: g++-6
BUILD_OPT: 1
USE_64: 1
extra:
treeherder:
build:
platform: linux64
machine:
platform: linux64
collection:
opt: true
groupSymbol: Builds
groupName: Various builds
symbol: gcc-6.1
- task:
metadata:
name: "Linux 64 (opt, NSS_NO_PKCS11_BYPASS=1)"
description: "Linux 64 (opt, NSS_NO_PKCS11_BYPASS=1)"
payload:
env:
NSS_NO_PKCS11_BYPASS: 1
BUILD_OPT: 1
USE_64: 1
extra:
treeherder:
build:
platform: linux64
machine:
platform: linux64
collection:
opt: true
groupSymbol: Builds
groupName: Various builds
symbol: noPkcs11Bypass

Просмотреть файл

@ -4,7 +4,15 @@
"private": true,
"author": "Tim Taubert <ttaubert@mozilla.com>",
"description": "Decision Task for NSS",
"scripts": {
"compile": "babel-compile -p taskcluster src:lib",
"install": "npm run compile"
},
"dependencies": {
"babel-cli": "^6.14.0",
"babel-compile": "^2.0.0",
"babel-preset-taskcluster": "^3.0.0",
"babel-runtime": "^6.11.6",
"flatmap": "0.0.3",
"intersect": "^1.0.1",
"js-yaml": "^3.6.1",

Просмотреть файл

@ -0,0 +1,40 @@
/* 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/. */
import fs from "fs";
import path from "path";
import crypto from "crypto";
import flatmap from "flatmap";
// Compute the SHA-256 digest.
function sha256(data) {
let hash = crypto.createHash("sha256");
hash.update(data);
return hash.digest("hex");
}
// Recursively collect a list of all files of a given directory.
function collectFilesInDirectory(dir) {
return flatmap(fs.readdirSync(dir), entry => {
let entry_path = path.join(dir, entry);
if (fs.lstatSync(entry_path).isDirectory()) {
return collectFilesInDirectory(entry_path);
}
return [entry_path];
});
}
// Compute a context hash for the given context path.
export default function (context_path) {
let root = path.join(__dirname, "../../../..");
let dir = path.join(root, context_path);
let files = collectFilesInDirectory(dir).sort();
let hashes = files.map(file => {
return sha256(file + "|" + fs.readFileSync(file, "utf-8"));
});
return sha256(hashes.join(","));
}

Просмотреть файл

@ -0,0 +1,381 @@
/* 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/. */
import merge from "./merge";
import * as queue from "./queue";
const LINUX_IMAGE = {name: "linux", path: "automation/taskcluster/docker"};
const WINDOWS_CHECKOUT_CMD =
"bash -c \"hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss || " +
"(sleep 2; hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss) || " +
"(sleep 5; hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss)\"";
/*****************************************************************************/
queue.filter(task => {
if (task.group == "Builds") {
// Remove extra builds on ASan and ARM.
if (task.collection == "asan" || task.collection == "arm-debug") {
return false;
}
// Remove extra builds w/o libpkix for non-linux64-debug.
if (task.symbol == "noLibpkix" &&
(task.platform != "linux64" || task.collection != "debug")) {
return false;
}
}
return true;
});
queue.map(task => {
if (task.collection == "asan") {
// CRMF and FIPS tests still leak, unfortunately.
if (task.tests == "crmf" || task.tests == "fips") {
task.env.ASAN_OPTIONS = "detect_leaks=0";
}
// SSL(standard) runs on ASan take some time.
if (task.tests == "ssl" && task.cycle == "standard") {
task.maxRunTime = 7200;
}
}
if (task.collection == "arm-debug") {
// These tests take quite some time on our poor ARM devices.
if (task.tests == "chains" || (task.tests == "ssl" && task.cycle == "standard")) {
task.maxRunTime = 14400;
}
}
return task;
});
/*****************************************************************************/
export default async function main() {
await scheduleLinux("Linux 32 (opt)", {
env: {BUILD_OPT: "1"},
platform: "linux32",
image: LINUX_IMAGE
});
await scheduleLinux("Linux 32 (debug)", {
platform: "linux32",
collection: "debug",
image: LINUX_IMAGE
});
await scheduleLinux("Linux 64 (opt)", {
env: {USE_64: "1", BUILD_OPT: "1"},
platform: "linux64",
image: LINUX_IMAGE
});
await scheduleLinux("Linux 64 (debug)", {
env: {USE_64: "1"},
platform: "linux64",
collection: "debug",
image: LINUX_IMAGE
});
await scheduleLinux("Linux 64 (ASan, debug)", {
env: {
NSS_DISABLE_ARENA_FREE_LIST: "1",
NSS_DISABLE_UNLOAD: "1",
GCC_VERSION: "clang",
GXX_VERSION: "clang++",
USE_ASAN: "1",
USE_64: "1"
},
platform: "linux64",
collection: "asan",
image: LINUX_IMAGE
});
await scheduleWindows("Windows 2012 64 (opt)", {
env: {BUILD_OPT: "1"}
});
await scheduleWindows("Windows 2012 64 (debug)", {
collection: "debug"
});
await scheduleTools();
await scheduleLinux("Linux 32 (ARM, debug)", {
image: "ttaubert/nss-rpi-ci:0.0.3",
provisioner: "localprovisioner",
collection: "arm-debug",
workerType: "nss-rpi",
platform: "linux32",
maxRunTime: 7200,
tier: 3
});
}
/*****************************************************************************/
async function scheduleLinux(name, base) {
// Build base definition.
let build_base = merge(base, {
command: [
"/bin/bash",
"-c",
"bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh"
],
artifacts: {
public: {
expires: 24 * 7,
type: "directory",
path: "/home/worker/artifacts"
}
},
kind: "build",
symbol: "B"
});
// The task that builds NSPR+NSS.
let task_build = queue.scheduleTask(merge(build_base, {name}));
// The task that generates certificates.
let task_cert = queue.scheduleTask(merge(build_base, {
name: "Certificates",
command: [
"/bin/bash",
"-c",
"bin/checkout.sh && nss/automation/taskcluster/scripts/gen_certs.sh"
],
parent: task_build,
symbol: "Certs"
}));
// Schedule tests.
scheduleTests(task_build, task_cert, merge(base, {
command: [
"/bin/bash",
"-c",
"bin/checkout.sh && nss/automation/taskcluster/scripts/run_tests.sh"
]
}));
// Extra builds.
let extra_base = merge({group: "Builds"}, build_base);
queue.scheduleTask(merge(extra_base, {
name: `${name} w/ clang-3.9`,
env: {
GCC_VERSION: "clang",
GXX_VERSION: "clang++"
},
symbol: "clang-3.9"
}));
queue.scheduleTask(merge(extra_base, {
name: `${name} w/ gcc-4.8`,
env: {
GCC_VERSION: "gcc-4.8",
GXX_VERSION: "g++-4.8"
},
symbol: "gcc-4.8"
}));
queue.scheduleTask(merge(extra_base, {
name: `${name} w/ gcc-6.1`,
env: {
GCC_VERSION: "gcc-6",
GXX_VERSION: "g++-6"
},
symbol: "gcc-6.1"
}));
queue.scheduleTask(merge(extra_base, {
name: `${name} w/ NSS_NO_PKCS11_BYPASS=1`,
env: {NSS_NO_PKCS11_BYPASS: "1"},
symbol: "noPkcs11Bypass"
}));
queue.scheduleTask(merge(extra_base, {
name: `${name} w/ NSS_DISABLE_LIBPKIX=1`,
env: {NSS_DISABLE_LIBPKIX: "1"},
symbol: "noLibpkix"
}));
return queue.submit();
}
/*****************************************************************************/
async function scheduleWindows(name, base) {
base = merge(base, {
workerType: "nss-win2012r2",
platform: "windows2012-64",
env: {
PATH: "c:\\mozilla-build\\python;c:\\mozilla-build\\msys\\local\\bin;" +
"c:\\mozilla-build\\7zip;c:\\mozilla-build\\info-zip;" +
"c:\\mozilla-build\\python\\Scripts;c:\\mozilla-build\\yasm;" +
"c:\\mozilla-build\\msys\\bin;c:\\Windows\\system32;" +
"c:\\mozilla-build\\upx391w;c:\\mozilla-build\\moztools-x64\\bin;" +
"c:\\mozilla-build\\wget",
DOMSUF: "localdomain",
HOST: "localhost",
USE_64: "1"
}
});
// Build base definition.
let build_base = merge(base, {
command: [
WINDOWS_CHECKOUT_CMD,
"bash -c nss/automation/taskcluster/windows/build.sh"
],
artifacts: [{
expires: 24 * 7,
type: "directory",
path: "public\\build"
}],
kind: "build",
symbol: "B"
});
// The task that builds NSPR+NSS.
let task_build = queue.scheduleTask(merge(build_base, {name}));
// The task that generates certificates.
let task_cert = queue.scheduleTask(merge(build_base, {
name: "Certificates",
command: [
WINDOWS_CHECKOUT_CMD,
"bash -c nss/automation/taskcluster/windows/gen_certs.sh"
],
parent: task_build,
symbol: "Certs"
}));
// Schedule tests.
scheduleTests(task_build, task_cert, merge(base, {
command: [
WINDOWS_CHECKOUT_CMD,
"bash -c nss/automation/taskcluster/windows/run_tests.sh"
]
}));
// Extra builds.
let extra_base = merge({group: "Builds"}, build_base);
queue.scheduleTask(merge(extra_base, {
name: `${name} w/ NSS_NO_PKCS11_BYPASS=1`,
env: {NSS_NO_PKCS11_BYPASS: "1"},
symbol: "noPkcs11Bypass"
}));
return queue.submit();
}
/*****************************************************************************/
function scheduleTests(task_build, task_cert, test_base) {
test_base = merge({kind: "test"}, test_base);
// Schedule tests that do NOT need certificates.
let no_cert_base = merge(test_base, {parent: task_build});
queue.scheduleTask(merge(no_cert_base, {
name: "Gtests", symbol: "Gtest", tests: "ssl_gtests gtests"
}));
queue.scheduleTask(merge(no_cert_base, {
name: "Chains tests", symbol: "Chains", tests: "chains"
}));
queue.scheduleTask(merge(no_cert_base, {
name: "Cipher tests", symbol: "Cipher", tests: "cipher"
}));
queue.scheduleTask(merge(no_cert_base, {
name: "EC tests", symbol: "EC", tests: "ec"
}));
queue.scheduleTask(merge(no_cert_base, {
name: "Lowhash tests", symbol: "Lowhash", tests: "lowhash"
}));
queue.scheduleTask(merge(no_cert_base, {
name: "SDR tests", symbol: "SDR", tests: "sdr"
}));
// Schedule tests that need certificates.
let cert_base = merge(test_base, {parent: task_cert});
queue.scheduleTask(merge(cert_base, {
name: "CRMF tests", symbol: "CRMF", tests: "crmf"
}));
queue.scheduleTask(merge(cert_base, {
name: "DB tests", symbol: "DB", tests: "dbtests"
}));
queue.scheduleTask(merge(cert_base, {
name: "FIPS tests", symbol: "FIPS", tests: "fips"
}));
queue.scheduleTask(merge(cert_base, {
name: "Merge tests", symbol: "Merge", tests: "merge"
}));
queue.scheduleTask(merge(cert_base, {
name: "S/MIME tests", symbol: "SMIME", tests: "smime"
}));
queue.scheduleTask(merge(cert_base, {
name: "Tools tests", symbol: "Tools", tests: "tools"
}));
// SSL tests, need certificates too.
let ssl_base = merge(cert_base, {tests: "ssl", group: "SSL"});
queue.scheduleTask(merge(ssl_base, {
name: "SSL tests (standard)", symbol: "standard", cycle: "standard"
}));
queue.scheduleTask(merge(ssl_base, {
name: "SSL tests (pkix)", symbol: "pkix", cycle: "pkix"
}));
queue.scheduleTask(merge(ssl_base, {
name: "SSL tests (sharedb)", symbol: "sharedb", cycle: "sharedb"
}));
queue.scheduleTask(merge(ssl_base, {
name: "SSL tests (upgradedb)", symbol: "upgradedb", cycle: "upgradedb"
}));
}
/*****************************************************************************/
async function scheduleTools() {
let base = {
image: LINUX_IMAGE,
platform: "nss-tools",
kind: "test"
};
queue.scheduleTask(merge(base, {
symbol: "clang-format-3.9",
name: "clang-format-3.9",
command: [
"/bin/bash",
"-c",
"bin/checkout.sh && nss/automation/taskcluster/scripts/run_clang_format.sh"
]
}));
queue.scheduleTask(merge(base, {
symbol: "scan-build-3.9",
name: "scan-build-3.9",
env: {
USE_64: "1",
GCC_VERSION: "clang",
GXX_VERSION: "clang++"
},
artifacts: {
public: {
expires: 24,
type: "directory",
path: "/home/worker/artifacts"
}
},
command: [
"/bin/bash",
"-c",
"bin/checkout.sh && nss/automation/taskcluster/scripts/run_scan_build.sh"
]
}));
return queue.submit();
}

Просмотреть файл

@ -0,0 +1,62 @@
/* 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/. */
import * as queue from "./queue";
import context_hash from "./context_hash";
import taskcluster from "taskcluster-client";
async function taskHasImageArtifact(taskId) {
let queue = new taskcluster.Queue();
let {artifacts} = await queue.listLatestArtifacts(taskId);
return artifacts.some(artifact => artifact.name == "public/image.tar");
}
async function findTaskWithImageArtifact(ns) {
let index = new taskcluster.Index();
let {taskId} = await index.findTask(ns);
let has_image = await taskHasImageArtifact(taskId);
return has_image ? taskId : null;
}
export async function findTask({name, path}) {
let hash = await context_hash(path);
let ns = `docker.images.v1.${process.env.TC_PROJECT}.${name}.hash.${hash}`;
return findTaskWithImageArtifact(ns).catch(() => null);
}
export async function buildTask({name, path}) {
let hash = await context_hash(path);
let ns = `docker.images.v1.${process.env.TC_PROJECT}.${name}.hash.${hash}`;
return {
name: "Image Builder",
image: "taskcluster/image_builder:0.1.5",
routes: ["index." + ns],
env: {
HEAD_REPOSITORY: process.env.NSS_HEAD_REPOSITORY,
BASE_REPOSITORY: process.env.NSS_HEAD_REPOSITORY,
HEAD_REV: process.env.NSS_HEAD_REVISION,
HEAD_REF: process.env.NSS_HEAD_REVISION,
PROJECT: process.env.TC_PROJECT,
CONTEXT_PATH: path,
HASH: hash
},
artifacts: {
"public/image.tar": {
type: "file",
expires: 24 * 365,
path: "/artifacts/image.tar"
}
},
command: [
"/bin/bash",
"-c",
"/home/worker/bin/build_image.sh"
],
platform: "nss-decision",
features: ["dind"],
kind: "build",
symbol: "I"
};
}

Просмотреть файл

@ -0,0 +1,14 @@
/* 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/. */
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();
}
// Extend the task graph.
extend().catch(console.error);

Просмотреть файл

@ -0,0 +1,10 @@
/* 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/. */
import {recursive as merge} from "merge";
// We always want to clone.
export default function (...args) {
return merge(true, ...args);
}

Просмотреть файл

@ -0,0 +1,242 @@
/* 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/. */
import {clone} from "merge";
import merge from "./merge";
import slugid from "slugid";
import taskcluster from "taskcluster-client";
import * as image_builder from "./image_builder";
let maps = [];
let filters = [];
let tasks = new Map();
let image_tasks = new Map();
let queue = new taskcluster.Queue({
baseUrl: "http://taskcluster/queue/v1/"
});
function fromNow(hours) {
let d = new Date();
d.setHours(d.getHours() + (hours|0));
return d.toJSON();
}
function parseRoutes(routes) {
return [
`tc-treeherder.v2.${process.env.TC_PROJECT}.${process.env.NSS_HEAD_REVISION}.${process.env.NSS_PUSHLOG_ID}`,
...routes
];
}
function parseFeatures(list) {
return list.reduce((map, feature) => {
map[feature] = true;
return map;
}, {});
}
function parseArtifacts(artifacts) {
let copy = clone(artifacts);
Object.keys(copy).forEach(key => {
copy[key].expires = fromNow(copy[key].expires);
});
return copy;
}
function parseCollection(name) {
let collection = {};
collection[name] = true;
return collection;
}
function parseTreeherder(def) {
let treeherder = {
build: {
platform: def.platform
},
machine: {
platform: def.platform
},
symbol: def.symbol,
jobKind: def.kind
};
if (def.group) {
treeherder.groupSymbol = def.group;
}
if (def.collection) {
treeherder.collection = parseCollection(def.collection);
}
if (def.tier) {
treeherder.tier = def.tier;
}
return treeherder;
}
function convertTask(def) {
let dependencies = [];
let env = merge({
NSS_HEAD_REPOSITORY: process.env.NSS_HEAD_REPOSITORY,
NSS_HEAD_REVISION: process.env.NSS_HEAD_REVISION
}, def.env || {});
if (def.parent) {
dependencies.push(def.parent);
env.TC_PARENT_TASK_ID = def.parent;
}
if (def.tests) {
env.NSS_TESTS = def.tests;
}
if (def.cycle) {
env.NSS_CYCLES = def.cycle;
}
let payload = {
env,
command: def.command,
maxRunTime: def.maxRunTime || 3600
};
if (def.image) {
payload.image = def.image;
}
if (def.features) {
payload.features = parseFeatures(def.features);
}
if (def.artifacts) {
payload.artifacts = parseArtifacts(def.artifacts);
}
return {
provisionerId: def.provisioner || "aws-provisioner-v1",
workerType: def.workerType || "hg-worker",
schedulerId: "task-graph-scheduler",
created: fromNow(0),
deadline: fromNow(24),
dependencies,
routes: parseRoutes(def.routes || []),
metadata: {
name: def.name,
description: def.name,
owner: process.env.TC_OWNER,
source: process.env.TC_SOURCE
},
payload,
extra: {
treeherder: parseTreeherder(def)
}
};
}
export function map(fun) {
maps.push(fun);
}
export function filter(fun) {
filters.push(fun);
}
export function scheduleTask(def) {
let taskId = slugid.v4();
tasks.set(taskId, merge({}, def));
return taskId;
}
export async function submit() {
let promises = new Map();
for (let [taskId, task] of tasks) {
// Allow filtering tasks before we schedule them.
if (!filters.every(filter => filter(task))) {
continue;
}
// Allow changing tasks before we schedule them.
maps.forEach(map => { task = map(merge({}, task)) });
let log_id = `${task.name} @ ${task.platform}[${task.collection || "opt"}]`;
console.log(`+ Submitting ${log_id}.`);
let parent = task.parent;
// Convert the task definition.
task = await convertTask(task);
// Convert the docker image definition.
let image_def = task.payload.image;
if (image_def && image_def.hasOwnProperty("path")) {
let key = `${image_def.name}:${image_def.path}`;
let data = {};
// Check the cache first.
if (image_tasks.has(key)) {
data = image_tasks.get(key);
} else {
data.taskId = await image_builder.findTask(image_def);
data.isPending = !data.taskId;
// No task found.
if (data.isPending) {
let image_task = await image_builder.buildTask(image_def);
// Schedule a new image builder task immediately.
data.taskId = slugid.v4();
try {
await queue.createTask(data.taskId, convertTask(image_task));
} catch (e) {
console.error("! FAIL: Scheduling image builder task failed.");
continue; /* Skip this task on failure. */
}
}
// Store in cache.
image_tasks.set(key, data);
}
if (data.isPending) {
task.dependencies.push(data.taskId);
}
task.payload.image = {
path: "public/image.tar",
taskId: data.taskId,
type: "task-image"
};
}
// Wait for the parent task to be created before scheduling dependants.
let predecessor = parent ? promises.get(parent) : Promise.resolve();
promises.set(taskId, predecessor.then(() => {
// Schedule the task.
return queue.createTask(taskId, task).catch(err => {
console.error(`! FAIL: Scheduling ${log_id} failed.`, err);
});
}));
}
// Wait for all requests to finish.
if (promises.length) {
await Promise.all([...promises.values()]);
console.log("=== Total:", promises.length, "tasks. ===");
}
tasks.clear();
}

Просмотреть файл

@ -2,8 +2,9 @@
* 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/. */
var intersect = require("intersect");
var parse_args = require("minimist");
import * as queue from "./queue";
import intersect from "intersect";
import parse_args from "minimist";
function parseOptions(opts) {
opts = parse_args(opts.split(/\s+/), {
@ -13,7 +14,7 @@ function parseOptions(opts) {
});
// Parse build types (d=debug, o=opt).
var builds = intersect(opts.build.split(""), ["d", "o"]);
let builds = intersect(opts.build.split(""), ["d", "o"]);
// If the given value is nonsense default to debug and opt builds.
if (builds.length == 0) {
@ -21,8 +22,8 @@ function parseOptions(opts) {
}
// Parse platforms.
var allPlatforms = ["linux", "linux64", "linux64-asan", "win64", "arm"];
var platforms = intersect(opts.platform.split(/\s*,\s*/), allPlatforms);
let allPlatforms = ["linux", "linux64", "linux64-asan", "win64", "arm"];
let platforms = intersect(opts.platform.split(/\s*,\s*/), allPlatforms);
// If the given value is nonsense or "none" default to all platforms.
if (platforms.length == 0 && opts.platform != "none") {
@ -30,9 +31,9 @@ function parseOptions(opts) {
}
// Parse unit tests.
var allUnitTests = ["crmf", "chains", "cipher", "db", "ec", "fips", "gtest",
let allUnitTests = ["crmf", "chains", "cipher", "db", "ec", "fips", "gtest",
"lowhash", "merge", "sdr", "smime", "tools", "ssl"];
var unittests = intersect(opts.unittests.split(/\s*,\s*/), allUnitTests);
let unittests = intersect(opts.unittests.split(/\s*,\s*/), allUnitTests);
// If the given value is "all" run all tests.
// If it's nonsense then don't run any tests.
@ -43,8 +44,8 @@ function parseOptions(opts) {
}
// Parse tools.
var allTools = ["clang-format", "scan-build"];
var tools = intersect(opts.tools.split(/\s*,\s*/), allTools);
let allTools = ["clang-format", "scan-build"];
let tools = intersect(opts.tools.split(/\s*,\s*/), allTools);
// If the given value is "all" run all tools.
// If it's nonsense then don't run any tools.
@ -63,36 +64,20 @@ function parseOptions(opts) {
};
}
function filterTasks(tasks, comment) {
// Check for try syntax in changeset comment.
var match = comment.match(/^\s*try:\s*(.*)\s*$/);
if (!match) {
return tasks;
}
var opts = parseOptions(match[1]);
return tasks.filter(function (task) {
var env = task.task.payload.env || {};
var th = task.task.extra.treeherder;
var machine = th.machine.platform;
var coll = th.collection || {};
var found;
function filter(opts) {
return function (task) {
// Filter tools. We can immediately return here as those
// are not affected by platform or build type selectors.
if (machine == "nss-tools") {
return opts.tools.some(function (tool) {
var symbol = th.symbol.toLowerCase();
return symbol.startsWith(tool);
if (task.platform == "nss-tools") {
return opts.tools.some(tool => {
return task.symbol.toLowerCase().startsWith(tool);
});
}
// Filter unit tests.
if (env.NSS_TESTS && env.TC_PARENT_TASK_ID) {
found = opts.unittests.some(function (test) {
var symbol = (th.groupSymbol || th.symbol).toLowerCase();
return symbol.startsWith(test);
if (task.tests) {
let found = opts.unittests.some(test => {
return (task.group || task.symbol).toLowerCase().startsWith(test);
});
if (!found) {
@ -101,13 +86,15 @@ function filterTasks(tasks, comment) {
}
// Filter extra builds.
if (th.groupSymbol == "Builds" && !opts.extra) {
if (task.group == "Builds" && !opts.extra) {
return false;
}
let coll = name => name == (task.collection || "opt");
// Filter by platform.
found = opts.platforms.some(function (platform) {
var aliases = {
let found = opts.platforms.some(platform => {
let aliases = {
"linux": "linux32",
"linux64-asan": "linux64",
"win64": "windows2012-64",
@ -115,15 +102,15 @@ function filterTasks(tasks, comment) {
};
// Check the platform name.
var keep = machine == (aliases[platform] || platform);
let keep = (task.platform == (aliases[platform] || platform));
// Additional checks.
if (platform == "linux64-asan") {
keep &= coll.asan;
keep &= coll("asan");
} else if (platform == "arm") {
keep &= (coll["arm-opt"] || coll["arm-debug"]);
keep &= coll("arm-opt") || coll("arm-debug");
} else {
keep &= (coll.opt || coll.debug);
keep &= coll("opt") || coll("debug");
}
return keep;
@ -134,10 +121,20 @@ function filterTasks(tasks, comment) {
}
// Finally, filter by build type.
var isDebug = coll.debug || coll.asan || coll["arm-debug"];
return (isDebug && opts.builds.indexOf("d") > -1) ||
(!isDebug && opts.builds.indexOf("o") > -1);
});
let isDebug = coll("debug") || coll("asan") || coll("arm-debug");
return (isDebug && opts.builds.includes("d")) ||
(!isDebug && opts.builds.includes("o"));
}
}
module.exports.filterTasks = filterTasks;
export function initFilter() {
let comment = process.env.TC_COMMENT || "";
// Check for try syntax in changeset comment.
let match = comment.match(/^\s*try:\s*(.*)\s*$/);
// Add try syntax filter.
if (match) {
queue.filter(filter(parseOptions(match[1])));
}
}

Просмотреть файл

@ -1,14 +0,0 @@
---
- task:
metadata:
name: Chains tests
description: Chains tests
payload:
maxRunTime: 14400
env:
NSS_TESTS: chains
extra:
treeherder:
symbol: Chains

Просмотреть файл

@ -1,13 +0,0 @@
---
- task:
metadata:
name: Cipher tests
description: Cipher tests
payload:
env:
NSS_TESTS: cipher
extra:
treeherder:
symbol: Cipher

Просмотреть файл

@ -1,14 +0,0 @@
---
- task:
metadata:
name: CRMF tests
description: CRMF tests
payload:
env:
ASAN_OPTIONS: detect_leaks=0
NSS_TESTS: crmf
extra:
treeherder:
symbol: CRMF

Просмотреть файл

@ -1,13 +0,0 @@
---
- task:
metadata:
name: DB tests
description: DB tests
payload:
env:
NSS_TESTS: dbtests
extra:
treeherder:
symbol: DB

Просмотреть файл

@ -1,13 +0,0 @@
---
- task:
metadata:
name: EC tests
description: EC tests
payload:
env:
NSS_TESTS: ec
extra:
treeherder:
symbol: EC

Просмотреть файл

@ -1,14 +0,0 @@
---
- task:
metadata:
name: FIPS tests
description: FIPS tests
payload:
env:
ASAN_OPTIONS: detect_leaks=0
NSS_TESTS: fips
extra:
treeherder:
symbol: FIPS

Просмотреть файл

@ -1,13 +0,0 @@
---
- task:
metadata:
name: GTests
description: GTests
payload:
env:
NSS_TESTS: ssl_gtests gtests
extra:
treeherder:
symbol: GTest

Просмотреть файл

@ -1,13 +0,0 @@
---
- task:
metadata:
name: Lowhash tests
description: Lowhash tests
payload:
env:
NSS_TESTS: lowhash
extra:
treeherder:
symbol: Lowhash

Просмотреть файл

@ -1,13 +0,0 @@
---
- task:
metadata:
name: Merge tests
description: Merge tests
payload:
env:
NSS_TESTS: merge
extra:
treeherder:
symbol: Merge

Просмотреть файл

@ -1,13 +0,0 @@
---
- task:
metadata:
name: SDR tests
description: SDR tests
payload:
env:
NSS_TESTS: sdr
extra:
treeherder:
symbol: SDR

Просмотреть файл

@ -1,13 +0,0 @@
---
- task:
metadata:
name: S/MIME tests
description: S/MIME tests
payload:
env:
NSS_TESTS: smime
extra:
treeherder:
symbol: SMIME

Просмотреть файл

@ -1,65 +0,0 @@
---
- task:
metadata:
name: "SSL tests (standard)"
description: "SSL tests (standard)"
payload:
maxRunTime: 14400
env:
NSS_CYCLES: standard
NSS_TESTS: ssl
extra:
treeherder:
symbol: standard
groupSymbol: SSL
groupName: SSL tests
- task:
metadata:
name: "SSL tests (pkix)"
description: "SSL tests (pkix)"
payload:
env:
NSS_CYCLES: pkix
NSS_TESTS: ssl
extra:
treeherder:
symbol: pkix
groupSymbol: SSL
groupName: SSL tests
- task:
metadata:
name: "SSL tests (sharedb)"
description: "SSL tests (sharedb)"
payload:
env:
NSS_CYCLES: sharedb
NSS_TESTS: ssl
extra:
treeherder:
symbol: sharedb
groupSymbol: SSL
groupName: SSL tests
- task:
metadata:
name: "SSL tests (upgradedb)"
description: "SSL tests (upgradedb)"
payload:
env:
NSS_CYCLES: upgradedb
NSS_TESTS: ssl
extra:
treeherder:
symbol: upgradedb
groupSymbol: SSL
groupName: SSL tests

Просмотреть файл

@ -1,13 +0,0 @@
---
- task:
metadata:
name: Tools tests
description: Tools tests
payload:
env:
NSS_TESTS: tools
extra:
treeherder:
symbol: Tools

Просмотреть файл

@ -1,29 +0,0 @@
---
reruns: 0
task:
created: !from_now 0
deadline: !from_now 24
provisionerId: aws-provisioner-v1
workerType: hg-worker
schedulerId: task-graph-scheduler
metadata:
owner: !env TC_OWNER
source: !env TC_SOURCE
payload:
maxRunTime: 3600
image: automation/taskcluster/docker
env:
NSS_HEAD_REPOSITORY: !env NSS_HEAD_REPOSITORY
NSS_HEAD_REVISION: !env NSS_HEAD_REVISION
extra:
treeherder:
build:
platform: nss-tools
machine:
platform: nss-tools
jobKind: test

Просмотреть файл

@ -1,15 +0,0 @@
---
- task:
metadata:
name: clang-format-3.8
description: clang-format-3.8
payload:
command:
- "/bin/bash"
- "-c"
- "bin/checkout.sh && nss/automation/taskcluster/scripts/run_clang_format.sh"
extra:
treeherder:
symbol: clang-format-3.8

Просмотреть файл

@ -1,26 +0,0 @@
---
- task:
metadata:
name: scan-build-3.8
description: scan-build-3.8
payload:
artifacts:
public:
type: directory
path: /home/worker/artifacts
expires: !from_now 24
command:
- "/bin/bash"
- "-c"
- "bin/checkout.sh && nss/automation/taskcluster/scripts/run_scan_build.sh"
env:
GCC_VERSION: clang
GXX_VERSION: clang++
USE_64: 1
extra:
treeherder:
symbol: scan-build-3.8

Просмотреть файл

@ -1,37 +0,0 @@
---
reruns: 2
task:
created: !from_now 0
deadline: !from_now 24
provisionerId: aws-provisioner-v1
workerType: nss-win2012r2
schedulerId: task-graph-scheduler
metadata:
owner: !env TC_OWNER
source: !env TC_SOURCE
payload:
maxRunTime: 3600
artifacts:
- type: directory
path: "public\\build"
expires: !from_now 24
command:
- "bash -c \"hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss || (sleep 2; hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss) || (sleep 5; hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss)\""
- "bash -c nss/automation/taskcluster/windows/build.sh"
env:
PATH: "c:\\mozilla-build\\python;c:\\mozilla-build\\msys\\local\\bin;c:\\mozilla-build\\7zip;c:\\mozilla-build\\info-zip;c:\\mozilla-build\\python\\Scripts;c:\\mozilla-build\\yasm;c:\\mozilla-build\\msys\\bin;c:\\Windows\\system32;c:\\mozilla-build\\upx391w;c:\\mozilla-build\\moztools-x64\\bin;c:\\mozilla-build\\wget"
NSS_HEAD_REPOSITORY: !env NSS_HEAD_REPOSITORY
NSS_HEAD_REVISION: !env NSS_HEAD_REVISION
DOMSUF: localdomain
HOST: localhost
extra:
treeherder:
jobKind: build
symbol: B

Просмотреть файл

@ -1,24 +0,0 @@
---
reruns: 2
task:
created: !from_now 0
deadline: !from_now 24
provisionerId: aws-provisioner-v1
workerType: nss-win2012r2
schedulerId: task-graph-scheduler
metadata:
owner: !env TC_OWNER
source: !env TC_SOURCE
payload:
maxRunTime: 3600
command:
- "hg clone -r %NSS_HEAD_REVISION% %NSS_HEAD_REPOSITORY% nss"
- "bash -c nss/automation/taskcluster/windows/run_tests.sh"
extra:
treeherder:
jobKind: test

Просмотреть файл

@ -1,55 +0,0 @@
---
- task:
metadata:
name: "Windows 2012 64 (debug)"
description: "Windows 2012 64 (debug)"
payload:
env:
USE_64: 1
extra:
treeherder:
build:
platform: windows2012-64
machine:
platform: windows2012-64
collection:
debug: true
tests:
- chains
- cipher
- crmf
- db
- ec
- fips
- gtests
- lowhash
- merge
- sdr
- smime
- ssl
- tools
- task:
metadata:
name: "Windows 2012 64 (debug, NSS_NO_PKCS11_BYPASS=1)"
description: "Windows 2012 64 (debug, NSS_NO_PKCS11_BYPASS=1)"
payload:
env:
NSS_NO_PKCS11_BYPASS: 1
USE_64: 1
extra:
treeherder:
build:
platform: windows2012-64
machine:
platform: windows2012-64
collection:
debug: true
groupSymbol: Builds
groupName: Various builds
symbol: noPkcs11Bypass

Просмотреть файл

@ -1,57 +0,0 @@
---
- task:
metadata:
name: "Windows 2012 64 (opt)"
description: "Windows 2012 64 (opt)"
payload:
env:
BUILD_OPT: 1
USE_64: 1
extra:
treeherder:
build:
platform: windows2012-64
machine:
platform: windows2012-64
collection:
opt: true
tests:
- chains
- cipher
- crmf
- db
- ec
- fips
- gtests
- lowhash
- merge
- sdr
- smime
- ssl
- tools
- task:
metadata:
name: "Windows 2012 64 (opt, NSS_NO_PKCS11_BYPASS=1)"
description: "Windows 2012 64 (opt, NSS_NO_PKCS11_BYPASS=1)"
payload:
env:
NSS_NO_PKCS11_BYPASS: 1
BUILD_OPT: 1
USE_64: 1
extra:
treeherder:
build:
platform: windows2012-64
machine:
platform: windows2012-64
collection:
opt: true
groupSymbol: Builds
groupName: Various builds
symbol: noPkcs11Bypass

Просмотреть файл

@ -1,51 +0,0 @@
/* 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/. */
var fs = require("fs");
var yaml = require("js-yaml");
// Register custom YAML types.
var YAML_SCHEMA = yaml.Schema.create([
// Point in time at $now + x hours.
new yaml.Type('!from_now', {
kind: "scalar",
resolve: function (data) {
return true;
},
construct: function (data) {
var d = new Date();
d.setHours(d.getHours() + (data|0));
return d.toJSON();
}
}),
// Environment variables.
new yaml.Type('!env', {
kind: "scalar",
resolve: function (data) {
return true;
},
construct: function (data) {
return process.env[data] || "{{" + data.toLowerCase() + "}}";
}
})
]);
// Parse a given YAML file.
function parse(file, fallback) {
// Return fallback if the file doesn't exist.
if (!fs.existsSync(file) && fallback) {
return fallback;
}
// Otherwise, read the file or fail.
var source = fs.readFileSync(file, "utf-8");
return yaml.load(source, {schema: YAML_SCHEMA});
}
module.exports.parse = parse;

Просмотреть файл

@ -18,12 +18,6 @@ hg_clone https://hg.mozilla.org/projects/nspr nspr default
# Build.
make -C nss nss_build_all
# Generate certificates.
NSS_TESTS=cert NSS_CYCLES="standard pkix sharedb" $(dirname $0)/run_tests.sh
# Reset test counter so that test runs pick up our certificates.
echo 1 > tests_results/security/localhost
# Package.
mkdir artifacts
tar cvfjh artifacts/dist.tar.bz2 dist tests_results
tar cvfjh artifacts/dist.tar.bz2 dist

Просмотреть файл

@ -12,5 +12,5 @@ mkdir -p /home/worker/artifacts
# Install Node.JS dependencies.
cd nss/automation/taskcluster/graph/ && npm install
# Build the task graph definition.
nodejs build.js > /home/worker/artifacts/graph.json
# Extend the task graph.
node lib/index.js

Просмотреть файл

@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -v -e -x
source $(dirname $0)/tools.sh
if [ $(id -u) = 0 ]; then
# Set compiler.
switch_compilers
# Stupid Docker.
echo "127.0.0.1 localhost.localdomain" >> /etc/hosts
# Drop privileges by re-running this script.
exec su worker $0
fi
# Fetch artifact if needed.
fetch_dist
# Generate certificates.
NSS_TESTS=cert NSS_CYCLES="standard pkix sharedb" $(dirname $0)/run_tests.sh
# Reset test counter so that test runs pick up our certificates.
echo 1 > tests_results/security/localhost
# Package.
mkdir artifacts
tar cvfjh artifacts/dist.tar.bz2 dist tests_results

Просмотреть файл

@ -7,18 +7,12 @@ if [ $(id -u) -eq 0 ]; then
exec su worker $0 "$@"
fi
# Apply clang-format 3.8 on the provided folder and verify that this doesn't change any file.
# Apply clang-format on the provided folder and verify that this doesn't change any file.
# If any file differs after formatting, the script eventually exits with 1.
# Any differences between formatted and unformatted files is printed to stdout to give a hint what's wrong.
# Includes a default set of directories.
apply=false
if [ $1 = "--apply" ]; then
apply=true
shift
fi
if [ $# -gt 0 ]; then
dirs=("$@")
else
@ -47,15 +41,15 @@ else
)
fi
STATUS=0
for dir in "${dirs[@]}"; do
for i in $(find "$dir" -type f \( -name '*.[ch]' -o -name '*.cc' \) -print); do
if $apply; then
clang-format -i "$i"
elif ! clang-format "$i" | diff -Naur "$i" -; then
echo "Sorry, $i is not formatted properly. Please use clang-format 3.8 on your patch before landing."
STATUS=1
fi
done
find "$dir" -type f \( -name '*.[ch]' -o -name '*.cc' \) -exec clang-format -i {} \+
done
exit $STATUS
TMPFILE=$(mktemp /tmp/$(basename $0).XXXXXX)
trap 'rm $TMPFILE' exit
if (cd $(dirname $0); hg root >/dev/null 2>&1); then
hg diff --git "$top" | tee $TMPFILE
else
git -C "$top" diff | tee $TMPFILE
fi
[[ ! -s $TMPFILE ]]

Просмотреть файл

@ -2,9 +2,9 @@
set -v -e -x
if [ $(id -u) = 0 ]; then
source $(dirname $0)/tools.sh
source $(dirname $0)/tools.sh
if [ $(id -u) = 0 ]; then
# Set compiler.
switch_compilers
@ -16,10 +16,7 @@ if [ $(id -u) = 0 ]; then
fi
# Fetch artifact if needed.
if [ ! -d "dist" ]; then
curl --retry 3 -Lo dist.tar.bz2 https://queue.taskcluster.net/v1/task/$TC_PARENT_TASK_ID/artifacts/public/dist.tar.bz2
tar xvjf dist.tar.bz2
fi
fetch_dist
# Run tests.
cd nss/tests && ./all.sh

Просмотреть файл

@ -27,3 +27,15 @@ hg_clone() {
done
exit 1
}
fetch_dist() {
url=https://queue.taskcluster.net/v1/task/$TC_PARENT_TASK_ID/artifacts/public/dist.tar.bz2
if [ ! -d "dist" ]; then
for i in 0 2 5; do
sleep $i
curl --retry 3 -Lo dist.tar.bz2 $url && tar xvjf dist.tar.bz2 && return
rm -fr dist.tar.bz2 dist
done
exit 1
fi
}

Просмотреть файл

@ -11,11 +11,5 @@ hg_clone https://hg.mozilla.org/projects/nspr nspr default
# Build.
make -C nss nss_build_all
# Generate certificates.
NSS_TESTS=cert NSS_CYCLES="standard pkix sharedb" nss/tests/all.sh
# Reset test counter so that test runs pick up our certificates.
echo 1 > tests_results/security/localhost
# Package.
7z a public/build/dist.7z dist tests_results
7z a public/build/dist.7z dist

Просмотреть файл

@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -v -e -x
# Set up the toolchain.
source $(dirname $0)/setup.sh
# Fetch artifact.
wget -t 3 --retry-connrefused -w 5 --random-wait https://queue.taskcluster.net/v1/task/$TC_PARENT_TASK_ID/artifacts/public/build/dist.7z -O dist.7z
7z x dist.7z
# Generate certificates.
NSS_TESTS=cert NSS_CYCLES="standard pkix sharedb" nss/tests/all.sh
# Reset test counter so that test runs pick up our certificates.
echo 1 > tests_results/security/localhost
# Package.
7z a public/build/dist.7z dist tests_results

Просмотреть файл

@ -1,10 +1,10 @@
[
{
"version": "Visual Studio 2015 Update 3 14.0.25425.01 / SDK 10.0.14393.0",
"size": 326656969,
"digest": "babc414ffc0457d27f5a1ed24a8e4873afbe2f1c1a4075469a27c005e1babc3b2a788f643f825efedff95b79686664c67ec4340ed535487168a3482e68559bc7",
"version": "Visual Studio 2015 Update 2 / SDK 10.0.10586.0/212",
"size": 332442800,
"digest": "995394a4a515c7cb0f8595f26f5395361a638870dd0bbfcc22193fe1d98a0c47126057d5999cc494f3f3eac5cb49160e79757c468f83ee5797298e286ef6252c",
"algorithm": "sha512",
"filename": "vs2015u3.zip",
"filename": "vs2015u2.zip",
"unpack": true
}
]

Просмотреть файл

@ -18,7 +18,7 @@ hg_clone() {
hg_clone https://hg.mozilla.org/build/tools tools default
tools/scripts/tooltool/tooltool_wrapper.sh $(dirname $0)/releng.manifest https://api.pub.build.mozilla.org/tooltool/ non-existant-file.sh /c/mozilla-build/python/python.exe /c/builds/tooltool.py --authentication-file /c/builds/relengapi.tok -c /c/builds/tooltool_cache
VSPATH="$(pwd)/vs2015u3"
VSPATH="$(pwd)/vs2015u2"
export WINDOWSSDKDIR="${VSPATH}/SDK"
export WIN32_REDIST_DIR="${VSPATH}/VC/redist/x64/Microsoft.VC140.CRT"
@ -26,5 +26,5 @@ export WIN_UCRT_REDIST_DIR="${VSPATH}/SDK/Redist/ucrt/DLLs/x64"
export PATH="${VSPATH}/VC/bin/amd64:${VSPATH}/VC/bin:${VSPATH}/SDK/bin/x64:${VSPATH}/VC/redist/x64/Microsoft.VC140.CRT:${VSPATH}/SDK/Redist/ucrt/DLLs/x64:${PATH}"
export INCLUDE="${VSPATH}/VC/include:${VSPATH}/SDK/Include/10.0.14393.0/ucrt:${VSPATH}/SDK/Include/10.0.14393.0/shared:${VSPATH}/SDK/Include/10.0.14393.0/um"
export LIB="${VSPATH}/VC/lib/amd64:${VSPATH}/SDK/lib/10.0.14393.0/ucrt/x64:${VSPATH}/SDK/lib/10.0.14393.0/um/x64"
export INCLUDE="${VSPATH}/VC/include:${VSPATH}/SDK/Include/10.0.10586.0/ucrt:${VSPATH}/SDK/Include/10.0.10586.0/shared:${VSPATH}/SDK/Include/10.0.10586.0/um"
export LIB="${VSPATH}/VC/lib/amd64:${VSPATH}/SDK/lib/10.0.10586.0/ucrt/x64:${VSPATH}/SDK/lib/10.0.10586.0/um/x64"

Просмотреть файл

@ -687,12 +687,7 @@ static unsigned char
nibble(char c)
{
c = PORT_Tolower(c);
return (c >= '0' && c <= '9') ? c - '0' : (c >=
'a' &&
c <=
'f')
? c - 'a' + 10
: -1;
return (c >= '0' && c <= '9') ? c - '0' : (c >= 'a' && c <= 'f') ? c - 'a' + 10 : -1;
}
SECStatus

Просмотреть файл

@ -267,7 +267,7 @@ static void
error(long va_alist, ...)
#else
static void
error(Pk11Install_Error errcode, ...)
error(PRErrorCode errcode, ...)
#endif
{

Просмотреть файл

@ -10,4 +10,3 @@
*/
#error "Do not include this header file."

Просмотреть файл

@ -381,18 +381,15 @@ of the attribute codes:
<command>T</command> - trusted CA for client authentication (ssl server only)
</para>
</listitem>
<listitem>
<para>
<command>u</command> - user
</para>
</listitem>
</itemizedlist>
<para>
The attribute codes for the categories are separated by commas, and the entire set of attributes enclosed by quotation marks. For example:
</para>
<para><command>-t "TCu,Cu,Tu"</command></para>
<para><command>-t "TC,C,T"</command></para>
<para>
Use the -L option to see a list of the current certificates and trust attributes in a certificate database. </para></listitem>
Use the -L option to see a list of the current certificates and trust attributes in a certificate database. </para>
<para>
Note that the output of the -L option may include "u" flag, which means that there is a private key associated with the certificate. It is a dynamic flag and you cannot set it with certutil. </para></listitem>
</varlistentry>
<varlistentry>
@ -860,7 +857,7 @@ The interative prompts for key usage and whether any extensions are critical and
<para>
From there, new certificates can reference the self-signed certificate:
</para>
<programlisting>$ certutil -S -s "CN=My Server Cert" -n my-server-cert -c "my-ca-cert" -t "u,u,u" -1 -5 -6 -8 -m 730</programlisting>
<programlisting>$ certutil -S -s "CN=My Server Cert" -n my-server-cert -c "my-ca-cert" -t ",," -1 -5 -6 -8 -m 730</programlisting>
<para><command>Generating a Certificate from a Certificate Request</command></para>
<para>
@ -1023,11 +1020,11 @@ certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and
<para>
For example:
</para>
<programlisting>$ certutil -A -n "CN=My SSL Certificate" -t "u,u,u" -d sql:/home/my/sharednssdb -i /home/example-certs/cert.cer</programlisting>
<programlisting>$ certutil -A -n "CN=My SSL Certificate" -t ",," -d sql:/home/my/sharednssdb -i /home/example-certs/cert.cer</programlisting>
<para>
A related command option, <option>-E</option>, is used specifically to add email certificates to the certificate database. The <option>-E</option> command has the same arguments as the <option>-A</option> command. The trust arguments for certificates have the format <emphasis>SSL,S/MIME,Code-signing</emphasis>, so the middle trust settings relate most to email certificates (though the others can be set). For example:
</para>
<programlisting>$ certutil -E -n "CN=John Smith Email Cert" -t ",Pu," -d sql:/home/my/sharednssdb -i /home/example-certs/email.cer</programlisting>
<programlisting>$ certutil -E -n "CN=John Smith Email Cert" -t ",P," -d sql:/home/my/sharednssdb -i /home/example-certs/email.cer</programlisting>
<para><command>Deleting Certificates to the Database</command></para>
<para>
@ -1057,7 +1054,7 @@ certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and
<para>
For example:
</para>
<programlisting>$ certutil -M -n "My CA Certificate" -d sql:/home/my/sharednssdb -t "CTu,CTu,CTu"</programlisting>
<programlisting>$ certutil -M -n "My CA Certificate" -d sql:/home/my/sharednssdb -t "CT,CT,CT"</programlisting>
<para><command>Printing the Certificate Chain</command></para>
<para>

Просмотреть файл

@ -1,4 +1,4 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>CERTUTIL</title><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="index.html" title="CERTUTIL"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">CERTUTIL</th></tr></table><hr></div><div class="refentry"><a name="certutil"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>certutil — Manage keys and certificate in both NSS databases and other NSS tokens</p></div><div class="refsynopsisdiv"><h2>Synopsis</h2><div class="cmdsynopsis"><p><code class="command">certutil</code> [<em class="replaceable"><code>options</code></em>] [[<em class="replaceable"><code>arguments</code></em>]]</p></div></div><div class="refsection"><a name="idm139861295402064"></a><h2>STATUS</h2><p>This documentation is still work in progress. Please contribute to the initial review in <a class="ulink" href="https://bugzilla.mozilla.org/show_bug.cgi?id=836477" target="_top">Mozilla NSS bug 836477</a>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>CERTUTIL</title><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="index.html" title="CERTUTIL"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">CERTUTIL</th></tr></table><hr></div><div class="refentry"><a name="certutil"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>certutil — Manage keys and certificate in both NSS databases and other NSS tokens</p></div><div class="refsynopsisdiv"><h2>Synopsis</h2><div class="cmdsynopsis"><p><code class="command">certutil</code> [<em class="replaceable"><code>options</code></em>] [[<em class="replaceable"><code>arguments</code></em>]]</p></div></div><div class="refsection"><a name="idm139774553663312"></a><h2>STATUS</h2><p>This documentation is still work in progress. Please contribute to the initial review in <a class="ulink" href="https://bugzilla.mozilla.org/show_bug.cgi?id=836477" target="_top">Mozilla NSS bug 836477</a>
</p></div><div class="refsection"><a name="description"></a><h2>Description</h2><p>The Certificate Database Tool, <span class="command"><strong>certutil</strong></span>, is a command-line utility that can create and modify certificate and key databases. It can specifically list, generate, modify, or delete certificates, create or change the password, generate new public and private key pairs, display the contents of the key database, or delete key pairs within the key database.</p><p>Certificate issuance, part of the key and certificate management process, requires that keys and certificates be created in the key database. This document discusses certificate and key database management. For information on the security module database management, see the <span class="command"><strong>modutil</strong></span> manpage.</p></div><div class="refsection"><a name="options"></a><h2>Command Options and Arguments</h2><p>Running <span class="command"><strong>certutil</strong></span> always requires one and only one command option to specify the type of certificate operation. Each command option may take zero or more arguments. The command option <code class="option">-H</code> will list all the command options and their relevant arguments.</p><p><span class="command"><strong>Command Options</strong></span></p><div class="variablelist"><dl class="variablelist"><dt><span class="term">-A </span></dt><dd><p>Add an existing certificate to a certificate database. The certificate database should already exist; if one is not present, this command option will initialize one by default.</p></dd><dt><span class="term">-B</span></dt><dd><p>Run a series of commands from the specified batch file. This requires the <code class="option">-i</code> argument.</p></dd><dt><span class="term">-C </span></dt><dd><p>Create a new binary certificate file from a binary certificate request file. Use the <code class="option">-i</code> argument to specify the certificate request file. If this argument is not used, <span class="command"><strong>certutil</strong></span> prompts for a filename. </p></dd><dt><span class="term">-D </span></dt><dd><p>Delete a certificate from the certificate database.</p></dd><dt><span class="term">--rename </span></dt><dd><p>Change the database nickname of a certificate.</p></dd><dt><span class="term">-E </span></dt><dd><p>Add an email certificate to the certificate database.</p></dd><dt><span class="term">-F</span></dt><dd><p>Delete a private key from a key database. Specify the key to delete with the -n argument. Specify the database from which to delete the key with the
<code class="option">-d</code> argument. Use the <code class="option">-k</code> argument to specify explicitly whether to delete a DSA, RSA, or ECC key. If you don't use the <code class="option">-k</code> argument, the option looks for an RSA key matching the specified nickname.
</p><p>
@ -51,12 +51,11 @@ of the attribute codes:
<span class="command"><strong>C</strong></span> - Trusted CA (implies c)
</p></li><li class="listitem"><p>
<span class="command"><strong>T</strong></span> - trusted CA for client authentication (ssl server only)
</p></li><li class="listitem"><p>
<span class="command"><strong>u</strong></span> - user
</p></li></ul></div><p>
The attribute codes for the categories are separated by commas, and the entire set of attributes enclosed by quotation marks. For example:
</p><p><span class="command"><strong>-t "TCu,Cu,Tu"</strong></span></p><p>
Use the -L option to see a list of the current certificates and trust attributes in a certificate database. </p></dd><dt><span class="term">-u certusage</span></dt><dd><p>Specify a usage context to apply when validating a certificate with the -V option.</p><p>The contexts are the following:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p><span class="command"><strong>C</strong></span> (as an SSL client)</p></li><li class="listitem"><p><span class="command"><strong>V</strong></span> (as an SSL server)</p></li><li class="listitem"><p><span class="command"><strong>L</strong></span> (as an SSL CA)</p></li><li class="listitem"><p><span class="command"><strong>A</strong></span> (as Any CA)</p></li><li class="listitem"><p><span class="command"><strong>Y</strong></span> (Verify CA)</p></li><li class="listitem"><p><span class="command"><strong>S</strong></span> (as an email signer)</p></li><li class="listitem"><p><span class="command"><strong>R</strong></span> (as an email recipient)</p></li><li class="listitem"><p><span class="command"><strong>O</strong></span> (as an OCSP status responder)</p></li><li class="listitem"><p><span class="command"><strong>J</strong></span> (as an object signer)</p></li></ul></div></dd><dt><span class="term">-v valid-months</span></dt><dd><p>Set the number of months a new certificate will be valid. The validity period begins at the current system time unless an offset is added or subtracted with the <code class="option">-w</code> option. If this argument is not used, the default validity period is three months. </p></dd><dt><span class="term">-w offset-months</span></dt><dd><p>Set an offset from the current system time, in months,
</p><p><span class="command"><strong>-t "TC,C,T"</strong></span></p><p>
Use the -L option to see a list of the current certificates and trust attributes in a certificate database. </p><p>
Note that the output of the -L option may include "u" flag, which means that there is a private key associated with the certificate. It is a dynamic flag and you cannot set it with certutil. </p></dd><dt><span class="term">-u certusage</span></dt><dd><p>Specify a usage context to apply when validating a certificate with the -V option.</p><p>The contexts are the following:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p><span class="command"><strong>C</strong></span> (as an SSL client)</p></li><li class="listitem"><p><span class="command"><strong>V</strong></span> (as an SSL server)</p></li><li class="listitem"><p><span class="command"><strong>L</strong></span> (as an SSL CA)</p></li><li class="listitem"><p><span class="command"><strong>A</strong></span> (as Any CA)</p></li><li class="listitem"><p><span class="command"><strong>Y</strong></span> (Verify CA)</p></li><li class="listitem"><p><span class="command"><strong>S</strong></span> (as an email signer)</p></li><li class="listitem"><p><span class="command"><strong>R</strong></span> (as an email recipient)</p></li><li class="listitem"><p><span class="command"><strong>O</strong></span> (as an OCSP status responder)</p></li><li class="listitem"><p><span class="command"><strong>J</strong></span> (as an object signer)</p></li></ul></div></dd><dt><span class="term">-v valid-months</span></dt><dd><p>Set the number of months a new certificate will be valid. The validity period begins at the current system time unless an offset is added or subtracted with the <code class="option">-w</code> option. If this argument is not used, the default validity period is three months. </p></dd><dt><span class="term">-w offset-months</span></dt><dd><p>Set an offset from the current system time, in months,
for the beginning of a certificate's validity period. Use when creating
the certificate or adding it to a database. Express the offset in integers,
using a minus sign (-) to indicate a negative offset. If this argument is
@ -162,7 +161,7 @@ Generating key. This may take a few moments...
The interative prompts for key usage and whether any extensions are critical and responses have been ommitted for brevity.
</p><p>
From there, new certificates can reference the self-signed certificate:
</p><pre class="programlisting">$ certutil -S -s "CN=My Server Cert" -n my-server-cert -c "my-ca-cert" -t "u,u,u" -1 -5 -6 -8 -m 730</pre><p><span class="command"><strong>Generating a Certificate from a Certificate Request</strong></span></p><p>
</p><pre class="programlisting">$ certutil -S -s "CN=My Server Cert" -n my-server-cert -c "my-ca-cert" -t ",," -1 -5 -6 -8 -m 730</pre><p><span class="command"><strong>Generating a Certificate from a Certificate Request</strong></span></p><p>
When a certificate request is created, a certificate can be generated by using the request and then referencing a certificate authority signing certificate (the <span class="emphasis"><em>issuer</em></span> specified in the <code class="option">-c</code> argument). The issuing certificate must be in the certificate database in the specified directory.
</p><pre class="programlisting">certutil -C -c issuer -i cert-request-file -o output-file [-m serial-number] [-v valid-months] [-w offset-months] -d [sql:]directory [-1] [-2] [-3] [-4] [-5 keyword] [-6 keyword] [-7 emailAddress] [-8 dns-names]</pre><p>
For example:
@ -284,9 +283,9 @@ certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and
Existing certificates or certificate requests can be added manually to the certificate database, even if they were generated elsewhere. This uses the <code class="option">-A</code> command option.
</p><pre class="programlisting">certutil -A -n certname -t trustargs -d [sql:]directory [-a] [-i input-file]</pre><p>
For example:
</p><pre class="programlisting">$ certutil -A -n "CN=My SSL Certificate" -t "u,u,u" -d sql:/home/my/sharednssdb -i /home/example-certs/cert.cer</pre><p>
</p><pre class="programlisting">$ certutil -A -n "CN=My SSL Certificate" -t ",," -d sql:/home/my/sharednssdb -i /home/example-certs/cert.cer</pre><p>
A related command option, <code class="option">-E</code>, is used specifically to add email certificates to the certificate database. The <code class="option">-E</code> command has the same arguments as the <code class="option">-A</code> command. The trust arguments for certificates have the format <span class="emphasis"><em>SSL,S/MIME,Code-signing</em></span>, so the middle trust settings relate most to email certificates (though the others can be set). For example:
</p><pre class="programlisting">$ certutil -E -n "CN=John Smith Email Cert" -t ",Pu," -d sql:/home/my/sharednssdb -i /home/example-certs/email.cer</pre><p><span class="command"><strong>Deleting Certificates to the Database</strong></span></p><p>
</p><pre class="programlisting">$ certutil -E -n "CN=John Smith Email Cert" -t ",P," -d sql:/home/my/sharednssdb -i /home/example-certs/email.cer</pre><p><span class="command"><strong>Deleting Certificates to the Database</strong></span></p><p>
Certificates can be deleted from a database using the <code class="option">-D</code> option. The only required options are to give the security database directory and to identify the certificate nickname.
</p><pre class="programlisting">certutil -D -d [sql:]directory -n "nickname"</pre><p>
For example:
@ -298,7 +297,7 @@ certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and
The trust settings (which relate to the operations that a certificate is allowed to be used for) can be changed after a certificate is created or added to the database. This is especially useful for CA certificates, but it can be performed for any type of certificate.
</p><pre class="programlisting">certutil -M -n certificate-name -t trust-args -d [sql:]directory</pre><p>
For example:
</p><pre class="programlisting">$ certutil -M -n "My CA Certificate" -d sql:/home/my/sharednssdb -t "CTu,CTu,CTu"</pre><p><span class="command"><strong>Printing the Certificate Chain</strong></span></p><p>
</p><pre class="programlisting">$ certutil -M -n "My CA Certificate" -d sql:/home/my/sharednssdb -t "CT,CT,CT"</pre><p><span class="command"><strong>Printing the Certificate Chain</strong></span></p><p>
Certificates can be issued in <span class="emphasis"><em>chains</em></span> because every certificate authority itself has a certificate; when a CA issues a certificate, it essentially stamps that certificate with its own fingerprint. The <code class="option">-O</code> prints the full chain of a certificate, going from the initial CA (the root CA) through ever intermediary CA to the actual certificate. For example, for an email certificate with two CAs in the chain:
</p><pre class="programlisting">$ certutil -d sql:/home/my/sharednssdb -O -n "jsmith@example.com"
"Builtin Object Token:Thawte Personal Freemail CA" [E=personal-freemail@thawte.com,CN=Thawte Personal Freemail CA,OU=Certification Services Division,O=Thawte Consulting,L=Cape Town,ST=Western Cape,C=ZA]

Просмотреть файл

@ -2,12 +2,12 @@
.\" Title: CERTUTIL
.\" Author: [see the "Authors" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
.\" Date: 7 September 2016
.\" Date: 8 September 2016
.\" Manual: NSS Security Tools
.\" Source: nss-tools
.\" Language: English
.\"
.TH "CERTUTIL" "1" "7 September 2016" "nss-tools" "NSS Security Tools"
.TH "CERTUTIL" "1" "8 September 2016" "nss-tools" "NSS Security Tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@ -452,23 +452,13 @@ for each trust setting\&. In each category position, use none, any, or all of th
\- trusted CA for client authentication (ssl server only)
.RE
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
\fBu\fR
\- user
.RE
.sp
The attribute codes for the categories are separated by commas, and the entire set of attributes enclosed by quotation marks\&. For example:
.sp
\fB\-t "TCu,Cu,Tu"\fR
\fB\-t "TC,C,T"\fR
.sp
Use the \-L option to see a list of the current certificates and trust attributes in a certificate database\&.
.sp
Note that the output of the \-L option may include "u" flag, which means that there is a private key associated with the certificate\&. It is a dynamic flag and you cannot set it with certutil\&.
.RE
.PP
\-u certusage
@ -1322,7 +1312,7 @@ From there, new certificates can reference the self\-signed certificate:
.RS 4
.\}
.nf
$ certutil \-S \-s "CN=My Server Cert" \-n my\-server\-cert \-c "my\-ca\-cert" \-t "u,u,u" \-1 \-5 \-6 \-8 \-m 730
$ certutil \-S \-s "CN=My Server Cert" \-n my\-server\-cert \-c "my\-ca\-cert" \-t ",," \-1 \-5 \-6 \-8 \-m 730
.fi
.if n \{\
.RE
@ -1598,7 +1588,7 @@ For example:
.RS 4
.\}
.nf
$ certutil \-A \-n "CN=My SSL Certificate" \-t "u,u,u" \-d sql:/home/my/sharednssdb \-i /home/example\-certs/cert\&.cer
$ certutil \-A \-n "CN=My SSL Certificate" \-t ",," \-d sql:/home/my/sharednssdb \-i /home/example\-certs/cert\&.cer
.fi
.if n \{\
.RE
@ -1616,7 +1606,7 @@ command\&. The trust arguments for certificates have the format
.RS 4
.\}
.nf
$ certutil \-E \-n "CN=John Smith Email Cert" \-t ",Pu," \-d sql:/home/my/sharednssdb \-i /home/example\-certs/email\&.cer
$ certutil \-E \-n "CN=John Smith Email Cert" \-t ",P," \-d sql:/home/my/sharednssdb \-i /home/example\-certs/email\&.cer
.fi
.if n \{\
.RE
@ -1698,7 +1688,7 @@ For example:
.RS 4
.\}
.nf
$ certutil \-M \-n "My CA Certificate" \-d sql:/home/my/sharednssdb \-t "CTu,CTu,CTu"
$ certutil \-M \-n "My CA Certificate" \-d sql:/home/my/sharednssdb \-t "CT,CT,CT"
.fi
.if n \{\
.RE

Просмотреть файл

@ -24,6 +24,7 @@ CPPSRCS = \
ssl_ems_unittest.cc \
ssl_extension_unittest.cc \
ssl_gtest.cc \
ssl_hrr_unittest.cc \
ssl_loopback_unittest.cc \
ssl_record_unittest.cc \
ssl_resumption_unittest.cc \

Просмотреть файл

@ -4,8 +4,8 @@
* 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 "ssl.h"
#include "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"
@ -22,20 +22,19 @@ extern "C" {
namespace nss_test {
TEST_F(TlsConnectTest, DamageSecretHandleZeroRttClientFinished) {
TEST_P(TlsConnectTls13, ZeroRtt) {
SetupForZeroRtt();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
client_->SetPacketFilter(new AfterRecordN(
client_, server_,
0, // ClientHello.
[this]() { SSLInt_DamageEarlyTrafficSecret(server_->ssl_fd()); }));
ConnectExpectFail();
client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
ExpectResumption(RESUME_TICKET);
ZeroRttSendReceive(true);
Handshake();
ExpectEarlyDataAccepted(true);
CheckConnected();
SendReceive();
}
TEST_F(TlsConnectTest, ZeroRttServerRejectByOption) {
TEST_P(TlsConnectTls13, ZeroRttServerRejectByOption) {
SetupForZeroRtt();
client_->Set0RttEnabled(true);
ExpectResumption(RESUME_TICKET);
@ -45,7 +44,7 @@ TEST_F(TlsConnectTest, ZeroRttServerRejectByOption) {
SendReceive();
}
TEST_F(TlsConnectTest, ZeroRttServerForgetTicket) {
TEST_P(TlsConnectTls13, ZeroRttServerForgetTicket) {
SetupForZeroRtt();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
@ -58,11 +57,7 @@ TEST_F(TlsConnectTest, ZeroRttServerForgetTicket) {
SendReceive();
}
TEST_F(TlsConnectTest, ZeroRttServerOnly) {
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_3);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_3);
TEST_P(TlsConnectTls13, ZeroRttServerOnly) {
ExpectResumption(RESUME_NONE);
server_->Set0RttEnabled(true);
client_->StartConnect();
@ -84,19 +79,7 @@ TEST_F(TlsConnectTest, ZeroRttServerOnly) {
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
}
TEST_F(TlsConnectTest, ZeroRtt) {
SetupForZeroRtt();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
ExpectResumption(RESUME_TICKET);
ZeroRttSendReceive(true);
Handshake();
ExpectEarlyDataAccepted(true);
CheckConnected();
SendReceive();
}
TEST_F(TlsConnectTest, TestTls13ZeroRttAlpn) {
TEST_P(TlsConnectTls13, TestTls13ZeroRttAlpn) {
EnableAlpn();
SetupForZeroRtt();
EnableAlpn();
@ -114,28 +97,9 @@ TEST_F(TlsConnectTest, TestTls13ZeroRttAlpn) {
CheckAlpn("a");
}
// Remove the old ALPN value and so the client will not offer ALPN.
TEST_F(TlsConnectTest, TestTls13ZeroRttAlpnChangeBoth) {
EnableAlpn();
SetupForZeroRtt();
static const uint8_t alpn[] = {0x01, 0x62}; // "b"
EnableAlpn(alpn, sizeof(alpn));
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
ExpectResumption(RESUME_TICKET);
ZeroRttSendReceive(false, [this]() {
client_->CheckAlpn(SSL_NEXT_PROTO_NO_SUPPORT);
return false;
});
Handshake();
CheckConnected();
SendReceive();
CheckAlpn("b");
}
// Have the server negotiate a different ALPN value, and therefore
// reject 0-RTT.
TEST_F(TlsConnectTest, TestTls13ZeroRttAlpnChangeServer) {
TEST_P(TlsConnectTls13, TestTls13ZeroRttAlpnChangeServer) {
EnableAlpn();
SetupForZeroRtt();
static const uint8_t client_alpn[] = {0x01, 0x61, 0x01, 0x62}; // "a", "b"
@ -159,7 +123,7 @@ TEST_F(TlsConnectTest, TestTls13ZeroRttAlpnChangeServer) {
// Stomp the ALPN on the client after sending the ClientHello so
// that the server selection appears to be incorrect. The client
// should then fail the connection.
TEST_F(TlsConnectTest, TestTls13ZeroRttNoAlpnServer) {
TEST_P(TlsConnectTls13, TestTls13ZeroRttNoAlpnServer) {
EnableAlpn();
SetupForZeroRtt();
client_->Set0RttEnabled(true);
@ -181,7 +145,7 @@ TEST_F(TlsConnectTest, TestTls13ZeroRttNoAlpnServer) {
// Set up with no ALPN and then set the client so it thinks it has ALPN.
// The server responds without the extension and the client returns an
// error.
TEST_F(TlsConnectTest, TestTls13ZeroRttNoAlpnClient) {
TEST_P(TlsConnectTls13, TestTls13ZeroRttNoAlpnClient) {
SetupForZeroRtt();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
@ -197,4 +161,36 @@ TEST_F(TlsConnectTest, TestTls13ZeroRttNoAlpnClient) {
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}
// Remove the old ALPN value and so the client will not offer early data.
TEST_P(TlsConnectTls13, TestTls13ZeroRttAlpnChangeBoth) {
EnableAlpn();
SetupForZeroRtt();
static const uint8_t alpn[] = {0x01, 0x62}; // "b"
EnableAlpn(alpn, sizeof(alpn));
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
ExpectResumption(RESUME_TICKET);
ZeroRttSendReceive(false, [this]() {
client_->CheckAlpn(SSL_NEXT_PROTO_NO_SUPPORT);
return false;
});
Handshake();
CheckConnected();
SendReceive();
CheckAlpn("b");
}
TEST_F(TlsConnectTest, DamageSecretHandleZeroRttClientFinished) {
SetupForZeroRtt();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
client_->SetPacketFilter(new AfterRecordN(
client_, server_,
0, // ClientHello.
[this]() { SSLInt_DamageEarlyTrafficSecret(server_->ssl_fd()); }));
ConnectExpectFail();
client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
}
} // namespace nss_test

Просмотреть файл

@ -4,8 +4,8 @@
* 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 "ssl.h"
#include "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"
@ -68,12 +68,14 @@ TEST_P(TlsConnectGeneric, ClientAuthBigRsa) {
}
// Offset is the position in the captured buffer where the signature sits.
static void CheckSigAlgs(TlsInspectorRecordHandshakeMessage* capture,
size_t offset, TlsAgent* peer,
SSLHashType expected_hash, size_t expected_size) {
static void CheckSigScheme(TlsInspectorRecordHandshakeMessage* capture,
size_t offset, TlsAgent* peer,
uint16_t expected_scheme, size_t expected_size) {
EXPECT_LT(offset + 2U, capture->buffer().len());
EXPECT_EQ(expected_hash, capture->buffer().data()[offset]);
EXPECT_EQ(ssl_sign_rsa, capture->buffer().data()[offset + 1]);
uint32_t scheme = 0;
capture->buffer().Read(offset, 2, &scheme);
EXPECT_EQ(expected_scheme, static_cast<uint16_t>(scheme));
ScopedCERTCertificate remote_cert(SSL_PeerCertificate(peer->ssl_fd()));
ScopedSECKEYPublicKey remote_key(CERT_ExtractPublicKey(remote_cert.get()));
@ -97,7 +99,8 @@ TEST_P(TlsConnectTls12, ServerAuthCheckSigAlg) {
EXPECT_TRUE(buffer.Read(1, 2, &tmp)) << "read NamedCurve";
EXPECT_EQ(ssl_grp_ec_secp256r1, tmp);
EXPECT_TRUE(buffer.Read(3, 1, &tmp)) << " read ECPoint";
CheckSigAlgs(capture_ske, 4 + tmp, client_, ssl_hash_sha256, 1024);
CheckSigScheme(capture_ske, 4 + tmp, client_, kTlsSigSchemeRsaPssSha256,
1024);
}
TEST_P(TlsConnectTls12, ClientAuthCheckSigAlg) {
@ -110,7 +113,8 @@ TEST_P(TlsConnectTls12, ClientAuthCheckSigAlg) {
Connect();
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
CheckSigAlgs(capture_cert_verify, 0, server_, ssl_hash_sha1, 1024);
CheckSigScheme(capture_cert_verify, 0, server_, kTlsSigSchemeRsaPkcs1Sha1,
1024);
}
TEST_P(TlsConnectTls12, ClientAuthBigRsaCheckSigAlg) {
@ -122,7 +126,8 @@ TEST_P(TlsConnectTls12, ClientAuthBigRsaCheckSigAlg) {
server_->RequestClientAuth(true);
Connect();
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
CheckSigAlgs(capture_cert_verify, 0, server_, ssl_hash_sha256, 2048);
CheckSigScheme(capture_cert_verify, 0, server_, kTlsSigSchemeRsaPssSha256,
2048);
}
static const SSLSignatureAndHashAlg SignatureEcdsaSha384[] = {

Просмотреть файл

@ -4,10 +4,10 @@
* 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 "ssl.h"
#include <functional>
#include <memory>
#include "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"

Просмотреть файл

@ -4,10 +4,10 @@
* 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 "ssl.h"
#include <functional>
#include <memory>
#include "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"
@ -55,7 +55,7 @@ TEST_F(TlsConnectTest, DamageSecretHandleServerFinished) {
[this]() { SSLInt_DamageHsTrafficSecret(client_->ssl_fd()); }));
ConnectExpectFail();
client_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
server_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
}
} // namespace nspr_test

Просмотреть файл

@ -4,11 +4,11 @@
* 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 "ssl.h"
#include <functional>
#include <memory>
#include <set>
#include "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"
@ -26,52 +26,6 @@ TEST_P(TlsConnectGeneric, ConnectDhe) {
CheckKeys(ssl_kea_dh, ssl_auth_rsa_sign);
}
// Track groups and make sure that there are no duplicates.
class CheckDuplicateGroup {
public:
void AddAndCheckGroup(uint16_t group) {
EXPECT_EQ(groups_.end(), groups_.find(group))
<< "Group " << group << " should not be duplicated";
groups_.insert(group);
}
private:
std::set<uint16_t> groups_;
};
// Check the group of each of the supported groups
static void CheckGroups(const DataBuffer& groups,
std::function<void(uint16_t)> check_group) {
CheckDuplicateGroup group_set;
uint32_t tmp;
EXPECT_TRUE(groups.Read(0, 2, &tmp));
EXPECT_EQ(groups.len() - 2, static_cast<size_t>(tmp));
for (size_t i = 2; i < groups.len(); i += 2) {
EXPECT_TRUE(groups.Read(i, 2, &tmp));
uint16_t group = static_cast<uint16_t>(tmp);
group_set.AddAndCheckGroup(group);
check_group(group);
}
}
// Check the group of each of the shares
static void CheckShares(const DataBuffer& shares,
std::function<void(uint16_t)> check_group) {
CheckDuplicateGroup group_set;
uint32_t tmp;
EXPECT_TRUE(shares.Read(0, 2, &tmp));
EXPECT_EQ(shares.len() - 2, static_cast<size_t>(tmp));
size_t i;
for (i = 2; i < shares.len(); i += 4 + tmp) {
ASSERT_TRUE(shares.Read(i, 2, &tmp));
uint16_t group = static_cast<uint16_t>(tmp);
group_set.AddAndCheckGroup(group);
check_group(group);
ASSERT_TRUE(shares.Read(i + 2, 2, &tmp));
}
EXPECT_EQ(shares.len(), i);
}
TEST_P(TlsConnectTls13, SharesForBothEcdheAndDhe) {
EnsureTlsSetup();
client_->DisableAllCiphers();
@ -90,7 +44,7 @@ TEST_P(TlsConnectTls13, SharesForBothEcdheAndDhe) {
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
bool ec, dh;
auto track_group_type = [&ec, &dh](uint16_t group) {
auto track_group_type = [&ec, &dh](SSLNamedGroup group) {
if ((group & 0xff00U) == 0x100U) {
dh = true;
} else {
@ -118,7 +72,7 @@ TEST_P(TlsConnectTls13, NoDheOnEcdheConnections) {
Connect();
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
auto is_ecc = [](uint16_t group) { EXPECT_NE(0x100U, group & 0xff00U); };
auto is_ecc = [](SSLNamedGroup group) { EXPECT_NE(0x100U, group & 0xff00U); };
CheckGroups(groups_capture->extension(), is_ecc);
CheckShares(shares_capture->extension(), is_ecc);
}
@ -137,7 +91,7 @@ TEST_P(TlsConnectGeneric, ConnectFfdheClient) {
Connect();
CheckKeys(ssl_kea_dh, ssl_auth_rsa_sign);
auto is_ffdhe = [](uint16_t group) {
auto is_ffdhe = [](SSLNamedGroup group) {
// The group has to be in this range.
EXPECT_LE(ssl_grp_ffdhe_2048, group);
EXPECT_GE(ssl_grp_ffdhe_8192, group);
@ -507,7 +461,8 @@ TEST_P(TlsConnectGenericPre13, WeakDHGroup) {
TEST_P(TlsConnectGeneric, Ffdhe3072) {
EnableOnlyDheCiphers();
client_->ConfigNamedGroup(ssl_grp_ffdhe_2048, false);
SSLNamedGroup groups[] = {ssl_grp_ffdhe_3072};
client_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
Connect();
}
@ -523,6 +478,22 @@ TEST_P(TlsConnectGenericPre13, PreferredFfdhe) {
CheckKeys(ssl_kea_dh, ssl_auth_rsa_sign, 3072);
}
TEST_P(TlsConnectGenericPre13, MismatchDHE) {
EnableOnlyDheCiphers();
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE));
static const SSLDHEGroupType serverGroups[] = {ssl_ff_dhe_3072_group};
EXPECT_EQ(SECSuccess, SSL_DHEGroupPrefSet(server_->ssl_fd(), serverGroups,
PR_ARRAY_SIZE(serverGroups)));
static const SSLDHEGroupType clientGroups[] = {ssl_ff_dhe_2048_group};
EXPECT_EQ(SECSuccess, SSL_DHEGroupPrefSet(client_->ssl_fd(), clientGroups,
PR_ARRAY_SIZE(clientGroups)));
ConnectExpectFail();
server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
}
TEST_P(TlsConnectTls13, ResumeFfdhe) {
EnableOnlyDheCiphers();
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
@ -534,10 +505,10 @@ TEST_P(TlsConnectTls13, ResumeFfdhe) {
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
EnableOnlyDheCiphers();
TlsExtensionCapture* clientCapture =
new TlsExtensionCapture(kTlsExtensionPreSharedKey);
new TlsExtensionCapture(ssl_tls13_pre_shared_key_xtn);
client_->SetPacketFilter(clientCapture);
TlsExtensionCapture* serverCapture =
new TlsExtensionCapture(kTlsExtensionPreSharedKey);
new TlsExtensionCapture(ssl_tls13_pre_shared_key_xtn);
server_->SetPacketFilter(serverCapture);
ExpectResumption(RESUME_TICKET);
Connect();

Просмотреть файл

@ -4,8 +4,8 @@
* 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 "ssl.h"
#include "secerr.h"
#include "ssl.h"
extern "C" {
// This is not something that should make you happy.
@ -20,25 +20,6 @@ extern "C" {
namespace nss_test {
// This class selectively drops complete writes. This relies on the fact that
// writes in libssl are on record boundaries.
class SelectiveDropFilter : public PacketFilter, public PollTarget {
public:
SelectiveDropFilter(uint32_t pattern) : pattern_(pattern), counter_(0) {}
protected:
virtual Action Filter(const DataBuffer& input, DataBuffer* output) override {
if (counter_ >= 32) {
return KEEP;
}
return ((1 << counter_++) & pattern_) ? DROP : KEEP;
}
private:
const uint32_t pattern_;
uint8_t counter_;
};
TEST_P(TlsConnectDatagram, DropClientFirstFlightOnce) {
client_->SetPacketFilter(new SelectiveDropFilter(0x1));
Connect();

Просмотреть файл

@ -4,10 +4,10 @@
* 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 "ssl.h"
#include <functional>
#include <memory>
#include "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"
@ -51,33 +51,233 @@ TEST_P(TlsConnectGeneric, ConnectEcdhe) {
// If we pick a 256-bit cipher suite and use a P-384 certificate, the server
// should choose P-384 for key exchange too. Only valid for TLS >=1.2 because
// we don't have 256-bit ciphers before then.
// TODO: Re-enable for 1.3 when Bug 1286140 lands.
TEST_P(TlsConnectTls12, ConnectEcdheP384) {
TEST_P(TlsConnectTls12Plus, ConnectEcdheP384) {
Reset(TlsAgent::kServerEcdsa384);
ConnectWithCipherSuite(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);
CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa, 384);
}
TEST_P(TlsConnectGeneric, ConnectEcdheP384) {
TEST_P(TlsConnectGeneric, ConnectEcdheP384Client) {
EnsureTlsSetup();
client_->ConfigNamedGroup(ssl_grp_ec_secp256r1, false);
const SSLNamedGroup groups[] = {ssl_grp_ec_secp384r1, ssl_grp_ffdhe_2048};
client_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
server_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
Connect();
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign, 384);
}
// This causes a HelloRetryRequest in TLS 1.3. Earlier versions don't care.
TEST_P(TlsConnectGeneric, ConnectEcdheP384Server) {
EnsureTlsSetup();
auto hrr_capture =
new TlsInspectorRecordHandshakeMessage(kTlsHandshakeHelloRetryRequest);
server_->SetPacketFilter(hrr_capture);
const SSLNamedGroup groups[] = {ssl_grp_ec_secp384r1};
server_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
Connect();
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign, 384);
EXPECT_EQ(version_ == SSL_LIBRARY_VERSION_TLS_1_3,
hrr_capture->buffer().len() != 0);
}
// This enables only P-256 on the client and disables it on the server.
// This test will fail when we add other groups that identify as ECDHE.
TEST_P(TlsConnectGeneric, ConnectEcdheGroupMismatch) {
EnsureTlsSetup();
client_->ConfigNamedGroup(ssl_grp_ec_secp256r1, true);
client_->ConfigNamedGroup(ssl_grp_ec_secp384r1, false);
client_->ConfigNamedGroup(ssl_grp_ec_secp521r1, false);
server_->ConfigNamedGroup(ssl_grp_ec_secp256r1, false);
const SSLNamedGroup clientGroups[] = {ssl_grp_ec_secp256r1,
ssl_grp_ffdhe_2048};
const SSLNamedGroup serverGroups[] = {ssl_grp_ffdhe_2048};
client_->ConfigNamedGroups(clientGroups, PR_ARRAY_SIZE(clientGroups));
server_->ConfigNamedGroups(serverGroups, PR_ARRAY_SIZE(serverGroups));
Connect();
CheckKeys(ssl_kea_dh, ssl_auth_rsa_sign);
}
class TlsKeyExchangeTest : public TlsConnectGeneric {
protected:
TlsExtensionCapture *groups_capture_;
TlsExtensionCapture *shares_capture_;
TlsInspectorRecordHandshakeMessage *capture_hrr_;
void EnsureKeyShareSetup(const SSLNamedGroup *groups, size_t num) {
EnsureTlsSetup();
groups_capture_ = new TlsExtensionCapture(ssl_supported_groups_xtn);
shares_capture_ = new TlsExtensionCapture(ssl_tls13_key_share_xtn);
std::vector<PacketFilter *> captures;
captures.push_back(groups_capture_);
captures.push_back(shares_capture_);
client_->SetPacketFilter(new ChainedPacketFilter(captures));
capture_hrr_ =
new TlsInspectorRecordHandshakeMessage(kTlsHandshakeHelloRetryRequest);
server_->SetPacketFilter(capture_hrr_);
if (groups) {
client_->ConfigNamedGroups(groups, num);
server_->ConfigNamedGroups(groups, num);
}
}
std::vector<SSLNamedGroup> GetGroupDetails(const DataBuffer &ext) {
uint32_t tmp = 0;
EXPECT_TRUE(ext.Read(0, 2, &tmp));
EXPECT_EQ(ext.len() - 2, static_cast<size_t>(tmp));
EXPECT_TRUE(ext.len() % 2 == 0);
std::vector<SSLNamedGroup> groups;
for (size_t i = 1; i < ext.len() / 2; i += 1) {
EXPECT_TRUE(ext.Read(2 * i, 2, &tmp));
groups.push_back(static_cast<SSLNamedGroup>(tmp));
}
return groups;
}
std::vector<SSLNamedGroup> GetShareDetails(const DataBuffer &ext) {
uint32_t tmp = 0;
EXPECT_TRUE(ext.Read(0, 2, &tmp));
EXPECT_EQ(ext.len() - 2, static_cast<size_t>(tmp));
std::vector<SSLNamedGroup> shares;
size_t i = 2;
while (i < ext.len()) {
EXPECT_TRUE(ext.Read(i, 2, &tmp));
shares.push_back(static_cast<SSLNamedGroup>(tmp));
EXPECT_TRUE(ext.Read(i + 2, 2, &tmp));
i += 4 + tmp;
}
EXPECT_EQ(ext.len(), i);
return shares;
}
void CheckKEXDetails(std::vector<SSLNamedGroup> expectedGroups,
std::vector<SSLNamedGroup> expectedShares) {
std::vector<SSLNamedGroup> groups =
GetGroupDetails(groups_capture_->extension());
EXPECT_EQ(expectedGroups, groups);
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
ASSERT_TRUE(expectedShares.size());
std::vector<SSLNamedGroup> shares =
GetShareDetails(shares_capture_->extension());
EXPECT_EQ(expectedShares, shares);
} else {
EXPECT_EQ(0U, shares_capture_->extension().len());
}
EXPECT_EQ(0U, capture_hrr_->buffer().len())
<< "we didn't expect a hello retry request.";
}
};
TEST_P(TlsKeyExchangeTest, P384Priority) {
/* P256, P384 and P521 are enabled. Both prefer P384. */
const SSLNamedGroup groups[] = {ssl_grp_ec_secp384r1, ssl_grp_ec_secp256r1,
ssl_grp_ec_secp521r1};
EnsureKeyShareSetup(groups, PR_ARRAY_SIZE(groups));
client_->DisableAllCiphers();
client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
Connect();
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign, 384);
std::vector<SSLNamedGroup> shares = {ssl_grp_ec_secp384r1};
std::vector<SSLNamedGroup> expected_groups(groups,
groups + PR_ARRAY_SIZE(groups));
CheckKEXDetails(expected_groups, shares);
}
TEST_P(TlsKeyExchangeTest, DuplicateGroupConfig) {
const SSLNamedGroup groups[] = {ssl_grp_ec_secp384r1, ssl_grp_ec_secp384r1,
ssl_grp_ec_secp384r1, ssl_grp_ec_secp256r1,
ssl_grp_ec_secp256r1};
EnsureKeyShareSetup(groups, PR_ARRAY_SIZE(groups));
client_->DisableAllCiphers();
client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
Connect();
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign, 384);
std::vector<SSLNamedGroup> shares = {ssl_grp_ec_secp384r1};
std::vector<SSLNamedGroup> expectedGroups = {ssl_grp_ec_secp384r1,
ssl_grp_ec_secp256r1};
CheckKEXDetails(expectedGroups, shares);
}
TEST_P(TlsKeyExchangeTest, P384PriorityDHEnabled) {
/* P256, P384, P521, and FFDHE2048 are enabled. Both prefer P384. */
const SSLNamedGroup groups[] = {ssl_grp_ec_secp384r1, ssl_grp_ffdhe_2048,
ssl_grp_ec_secp256r1, ssl_grp_ec_secp521r1};
EnsureKeyShareSetup(groups, PR_ARRAY_SIZE(groups));
Connect();
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign, 384);
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
std::vector<SSLNamedGroup> shares = {ssl_grp_ec_secp384r1};
std::vector<SSLNamedGroup> expected_groups(groups,
groups + PR_ARRAY_SIZE(groups));
CheckKEXDetails(expected_groups, shares);
} else {
std::vector<SSLNamedGroup> oldtlsgroups = {
ssl_grp_ec_secp384r1, ssl_grp_ec_secp256r1, ssl_grp_ec_secp521r1};
CheckKEXDetails(oldtlsgroups, std::vector<SSLNamedGroup>());
}
}
TEST_P(TlsConnectGenericPre13, P384PriorityOnServer) {
EnsureTlsSetup();
client_->DisableAllCiphers();
client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
/* The server prefers P384. It has to win. */
const SSLNamedGroup serverGroups[] = {
ssl_grp_ec_secp384r1, ssl_grp_ec_secp256r1, ssl_grp_ec_secp521r1};
server_->ConfigNamedGroups(serverGroups, PR_ARRAY_SIZE(serverGroups));
Connect();
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign, 384);
}
TEST_P(TlsConnectGenericPre13, P384PriorityFromModelSocket) {
#ifdef NSS_ECC_MORE_THAN_SUITE_B
// We can't run this test with a model socket and more than suite B.
return;
#endif
EnsureModelSockets();
/* Both prefer P384, set on the model socket. */
const SSLNamedGroup groups[] = {ssl_grp_ec_secp384r1, ssl_grp_ec_secp256r1,
ssl_grp_ec_secp521r1, ssl_grp_ffdhe_2048};
client_model_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
server_model_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
Connect();
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign, 384);
}
TEST_P(TlsConnectStreamPre13, ConfiguredGroupsRenegotiate) {
EnsureTlsSetup();
client_->DisableAllCiphers();
client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
const SSLNamedGroup serverGroups[] = {ssl_grp_ec_secp256r1,
ssl_grp_ec_secp384r1};
const SSLNamedGroup clientGroups[] = {ssl_grp_ec_secp384r1};
server_->ConfigNamedGroups(clientGroups, PR_ARRAY_SIZE(clientGroups));
client_->ConfigNamedGroups(serverGroups, PR_ARRAY_SIZE(serverGroups));
Connect();
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign, 384);
CheckConnected();
// The renegotiation has to use the same preferences as the original session.
server_->PrepareForRenegotiate();
client_->StartRenegotiate();
Handshake();
CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign, 384);
}
// Replace the point in the client key exchange message with an empty one
class ECCClientKEXFilter : public TlsHandshakeFilter {
public:
@ -136,4 +336,8 @@ TEST_P(TlsConnectGenericPre13, ConnectECDHEmptyClientPoint) {
server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH);
}
} // namespace nspr_test
INSTANTIATE_TEST_CASE_P(KeyExchangeTest, TlsKeyExchangeTest,
::testing::Combine(TlsConnectTestBase::kTlsModesAll,
TlsConnectTestBase::kTlsV11Plus));
} // namespace nss_test

Просмотреть файл

@ -4,8 +4,8 @@
* 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 "ssl.h"
#include "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"

Просмотреть файл

@ -542,8 +542,8 @@ TEST_P(TlsExtensionTest13, ModifyDraftVersionAndFail) {
EXPECT_EQ(SSL_ERROR_UNSUPPORTED_VERSION, server_->error_code());
}
// This test only works with TLS because the MAC error causes a
// timeout on the server.
// This test only works in stream mode because the MAC error causes a timeout on
// the server with datagram.
TEST_F(TlsExtensionTest13Stream, DropServerKeyShare) {
EnsureTlsSetup();
server_->SetPacketFilter(new TlsExtensionDropper(ssl_tls13_key_share_xtn));

Просмотреть файл

@ -1,7 +1,7 @@
#include "ssl.h"
#include "nspr.h"
#include "nss.h"
#include "prenv.h"
#include "ssl.h"
#include <cstdlib>

Просмотреть файл

@ -0,0 +1,197 @@
/* -*- 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"
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
namespace nss_test {
TEST_P(TlsConnectTls13, HelloRetryRequestAbortsZeroRtt) {
const char* k0RttData = "Such is life";
const PRInt32 k0RttDataLen = static_cast<PRInt32>(strlen(k0RttData));
SetupForZeroRtt(); // initial handshake as normal
const SSLNamedGroup groups[2] = {ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1};
server_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
ExpectResumption(RESUME_TICKET);
// Send first ClientHello and send 0-RTT data
auto capture_early_data = new TlsExtensionCapture(ssl_tls13_early_data_xtn);
client_->SetPacketFilter(capture_early_data);
client_->Handshake();
EXPECT_EQ(k0RttDataLen, PR_Write(client_->ssl_fd(), k0RttData,
k0RttDataLen)); // 0-RTT write.
EXPECT_LT(0U, capture_early_data->extension().len());
// Send the HelloRetryRequest
auto hrr_capture =
new TlsInspectorRecordHandshakeMessage(kTlsHandshakeHelloRetryRequest);
server_->SetPacketFilter(hrr_capture);
server_->Handshake();
EXPECT_LT(0U, hrr_capture->buffer().len());
// The server can't read
std::vector<uint8_t> buf(k0RttDataLen);
EXPECT_EQ(SECFailure, PR_Read(server_->ssl_fd(), buf.data(), k0RttDataLen));
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
// Make a new capture for the early data.
capture_early_data = new TlsExtensionCapture(ssl_tls13_early_data_xtn);
client_->SetPacketFilter(capture_early_data);
// Complete the handshake successfully
Handshake();
ExpectEarlyDataAccepted(false); // The server should reject 0-RTT
CheckConnected();
SendReceive();
EXPECT_EQ(0U, capture_early_data->extension().len());
}
class KeyShareReplayer : public TlsExtensionFilter {
public:
KeyShareReplayer() {}
virtual PacketFilter::Action FilterExtension(uint16_t extension_type,
const DataBuffer& input,
DataBuffer* output) {
if (extension_type != ssl_tls13_key_share_xtn) {
return KEEP;
}
if (!data_.len()) {
data_ = input;
return KEEP;
}
*output = data_;
return CHANGE;
}
private:
DataBuffer data_;
};
// This forces a HelloRetryRequest by disabling P-256 on the server. However,
// the second ClientHello is modified so that it omits the requested share. The
// server should reject this.
TEST_P(TlsConnectTls13, RetryWithSameKeyShare) {
EnsureTlsSetup();
client_->SetPacketFilter(new KeyShareReplayer());
const SSLNamedGroup groups[2] = {ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1};
server_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
ConnectExpectFail();
EXPECT_EQ(SSL_ERROR_BAD_2ND_CLIENT_HELLO, server_->error_code());
EXPECT_EQ(SSL_ERROR_ILLEGAL_PARAMETER_ALERT, client_->error_code());
}
// This tests that the second attempt at sending a ClientHello (after receiving
// a HelloRetryRequest) is correctly retransmitted.
TEST_F(TlsConnectDatagram13, DropClientSecondFlightWithHelloRetry) {
const SSLNamedGroup groups[2] = {ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1};
server_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
server_->SetPacketFilter(new SelectiveDropFilter(0x2));
Connect();
}
TEST_F(TlsConnectTest, Select12AfterHelloRetryRequest) {
EnsureTlsSetup();
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
const SSLNamedGroup groups[2] = {ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1};
server_->ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
client_->StartConnect();
server_->StartConnect();
client_->Handshake();
server_->Handshake();
// Here we replace the TLS server with one that does TLS 1.2 only.
// This will happily send the client a TLS 1.2 ServerHello.
TlsAgent* replacement_server =
new TlsAgent(server_->name(), TlsAgent::SERVER, mode_);
delete server_;
server_ = replacement_server;
server_->Init();
client_->SetPeer(server_);
server_->SetPeer(client_);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_2);
ConnectExpectFail();
EXPECT_EQ(SSL_ERROR_ILLEGAL_PARAMETER_ALERT, server_->error_code());
EXPECT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
}
class HelloRetryRequestAgentTest : public TlsAgentTestClient {
protected:
void MakeHelloRetryRequestRecord(SSLNamedGroup group, DataBuffer* hrr_record,
uint32_t seq_num = 0) const {
const uint8_t canned_hrr[] = {
SSL_LIBRARY_VERSION_TLS_1_3 >> 8,
SSL_LIBRARY_VERSION_TLS_1_3 & 0xff,
0,
0, // The cipher suite is ignored.
static_cast<uint8_t>(group >> 8),
static_cast<uint8_t>(group),
0,
0 // no extensions
};
DataBuffer hrr;
MakeHandshakeMessage(kTlsHandshakeHelloRetryRequest, canned_hrr,
sizeof(canned_hrr), &hrr, seq_num);
MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, hrr.data(),
hrr.len(), hrr_record, seq_num);
}
};
// Send two HelloRetryRequest messages in response to the ClientHello. The are
// constructed to appear legitimate by asking for a new share in each, so that
// the client has to count to work out that the server is being unreasonable.
TEST_P(HelloRetryRequestAgentTest, SendSecondHelloRetryRequest) {
EnsureInit();
agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3,
SSL_LIBRARY_VERSION_TLS_1_3);
agent_->StartConnect();
DataBuffer hrr_record;
MakeHelloRetryRequestRecord(ssl_grp_ec_secp384r1, &hrr_record, 0);
ProcessMessage(hrr_record, TlsAgent::STATE_CONNECTING);
MakeHelloRetryRequestRecord(ssl_grp_ec_secp521r1, &hrr_record, 1);
ProcessMessage(hrr_record, TlsAgent::STATE_ERROR,
SSL_ERROR_RX_UNEXPECTED_HELLO_RETRY_REQUEST);
}
// Here the client receives a HelloRetryRequest with a group that they already
// provided a share for.
TEST_P(HelloRetryRequestAgentTest, HandleBogusHelloRetryRequest) {
EnsureInit();
agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3,
SSL_LIBRARY_VERSION_TLS_1_3);
agent_->StartConnect();
DataBuffer hrr_record;
MakeHelloRetryRequestRecord(ssl_grp_ec_secp256r1, &hrr_record);
ProcessMessage(hrr_record, TlsAgent::STATE_ERROR,
SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST);
}
INSTANTIATE_TEST_CASE_P(HelloRetryRequestAgentTests, HelloRetryRequestAgentTest,
TlsConnectTestBase::kTlsModesAll);
} // namespace nss_test

Просмотреть файл

@ -4,10 +4,10 @@
* 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 "ssl.h"
#include <functional>
#include <memory>
#include "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"
@ -53,6 +53,8 @@ TEST_P(TlsConnectGeneric, ConnectAlpn) {
TEST_P(TlsConnectGeneric, ConnectAlpnClone) {
EnsureModelSockets();
client_model_->EnableAlpn(alpn_dummy_val_, sizeof(alpn_dummy_val_));
server_model_->EnableAlpn(alpn_dummy_val_, sizeof(alpn_dummy_val_));
Connect();
CheckAlpn("a");
}

Просмотреть файл

@ -3,8 +3,9 @@
/* 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 "ssl.h"
#include "nss.h"
#include "ssl.h"
#include "sslimpl.h"
#include "databuffer.h"

Просмотреть файл

@ -4,10 +4,10 @@
* 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 "ssl.h"
#include <functional>
#include <memory>
#include "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"
@ -328,7 +328,8 @@ TEST_F(TlsConnectTest, TestTls13ResumptionTwice) {
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
TlsExtensionCapture* c1 = new TlsExtensionCapture(kTlsExtensionPreSharedKey);
TlsExtensionCapture* c1 =
new TlsExtensionCapture(ssl_tls13_pre_shared_key_xtn);
client_->SetPacketFilter(c1);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_3);
@ -348,7 +349,8 @@ TEST_F(TlsConnectTest, TestTls13ResumptionTwice) {
Reset();
ClearStats();
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
TlsExtensionCapture* c2 = new TlsExtensionCapture(kTlsExtensionPreSharedKey);
TlsExtensionCapture* c2 =
new TlsExtensionCapture(ssl_tls13_pre_shared_key_xtn);
client_->SetPacketFilter(c2);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_3);
@ -388,7 +390,7 @@ TEST_F(TlsConnectTest, DisableClientPSKAndFailToResume) {
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
TlsExtensionCapture* capture =
new TlsExtensionCapture(kTlsExtensionPreSharedKey);
new TlsExtensionCapture(ssl_tls13_pre_shared_key_xtn);
client_->SetPacketFilter(capture);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_3);
@ -417,10 +419,10 @@ TEST_F(TlsConnectTest, DisableServerPSKAndFailToResume) {
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
TlsExtensionCapture* clientCapture =
new TlsExtensionCapture(kTlsExtensionPreSharedKey);
new TlsExtensionCapture(ssl_tls13_pre_shared_key_xtn);
client_->SetPacketFilter(clientCapture);
TlsExtensionCapture* serverCapture =
new TlsExtensionCapture(kTlsExtensionPreSharedKey);
new TlsExtensionCapture(ssl_tls13_pre_shared_key_xtn);
server_->SetPacketFilter(serverCapture);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_3);

Просмотреть файл

@ -4,10 +4,10 @@
* 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 "ssl.h"
#include <functional>
#include <memory>
#include "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"

Просмотреть файл

@ -4,8 +4,8 @@
* 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 "ssl.h"
#include "pk11pub.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"

Просмотреть файл

@ -4,8 +4,8 @@
* 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 "ssl.h"
#include "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"

Просмотреть файл

@ -260,6 +260,13 @@ static int32_t DummyReserved(PRFileDesc *f) {
DummyPrSocket::~DummyPrSocket() { Reset(); }
void DummyPrSocket::SetPacketFilter(PacketFilter *filter) {
if (filter_) {
delete filter_;
}
filter_ = filter;
}
void DummyPrSocket::Reset() {
delete filter_;
if (peer_) {

Просмотреть файл

@ -58,7 +58,7 @@ class DummyPrSocket {
DummyPrSocket* peer() const { return peer_; }
void SetPeer(DummyPrSocket* peer) { peer_ = peer; }
void SetPacketFilter(PacketFilter* filter) { filter_ = filter; }
void SetPacketFilter(PacketFilter* filter);
// Drops peer, packet filter and any outstanding packets.
void Reset();

Просмотреть файл

@ -92,6 +92,13 @@ TlsAgent::~TlsAgent() {
}
}
void TlsAgent::SetState(State state) {
if (state_ == state) return;
LOG("Changing state from " << state_ << " to " << state);
state_ = state;
}
bool TlsAgent::ConfigServerCert(const std::string& name, bool updateKeyBits,
const SSLExtraServerCertData* serverCertData) {
ScopedCERTCertificate cert(PK11_FindCertFromNickname(name.c_str(), nullptr));
@ -121,18 +128,10 @@ bool TlsAgent::ConfigServerCert(const std::string& name, bool updateKeyBits,
// (NIST P-256, P-384, and P-521) are enabled. Disable all other curves.
void TlsAgent::DisableLameGroups() {
#ifdef NSS_ECC_MORE_THAN_SUITE_B
static const SSLNamedGroup lame_groups[] = {
ssl_grp_ec_sect163k1, ssl_grp_ec_sect163r1, ssl_grp_ec_sect163r2,
ssl_grp_ec_sect193r1, ssl_grp_ec_sect193r2, ssl_grp_ec_sect233k1,
ssl_grp_ec_sect233r1, ssl_grp_ec_sect239k1, ssl_grp_ec_sect283k1,
ssl_grp_ec_sect283r1, ssl_grp_ec_sect409k1, ssl_grp_ec_sect409r1,
ssl_grp_ec_sect571k1, ssl_grp_ec_sect571r1, ssl_grp_ec_secp160k1,
ssl_grp_ec_secp160r1, ssl_grp_ec_secp160r2, ssl_grp_ec_secp192k1,
ssl_grp_ec_secp192r1, ssl_grp_ec_secp224k1, ssl_grp_ec_secp224r1,
ssl_grp_ec_secp256k1};
for (size_t i = 0; i < PR_ARRAY_SIZE(lame_groups); ++i) {
ConfigNamedGroup(lame_groups[i], false);
}
static const SSLNamedGroup groups[] = {
ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1,
ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072, ssl_grp_ffdhe_4096};
ConfigNamedGroups(groups, PR_ARRAY_SIZE(groups));
#endif
}
@ -290,9 +289,9 @@ void TlsAgent::EnableSingleCipher(uint16_t cipher) {
EXPECT_EQ(SECSuccess, rv);
}
void TlsAgent::ConfigNamedGroup(SSLNamedGroup group, bool en) {
void TlsAgent::ConfigNamedGroups(const SSLNamedGroup* groups, size_t num) {
EXPECT_TRUE(EnsureTlsSetup());
SECStatus rv = SSL_NamedGroupPrefSet(ssl_fd_, group, en ? PR_TRUE : PR_FALSE);
SECStatus rv = SSL_NamedGroupConfig(ssl_fd_, groups, num);
EXPECT_EQ(SECSuccess, rv);
}
@ -802,6 +801,7 @@ void TlsAgentTestBase::EnsureInit() {
void TlsAgentTestBase::ProcessMessage(const DataBuffer& buffer,
TlsAgent::State expected_state,
int32_t error_code) {
std::cerr << "Process message: " << buffer << std::endl;
EnsureInit();
agent_->adapter()->PacketReceived(buffer);
agent_->Handshake();
@ -830,19 +830,22 @@ void TlsAgentTestBase::MakeRecord(Mode mode, uint8_t type, uint16_t version,
void TlsAgentTestBase::MakeRecord(uint8_t type, uint16_t version,
const uint8_t* buf, size_t len,
DataBuffer* out, uint64_t seq_num) {
DataBuffer* out, uint64_t seq_num) const {
MakeRecord(mode_, type, version, buf, len, out, seq_num);
}
void TlsAgentTestBase::MakeHandshakeMessage(uint8_t hs_type,
const uint8_t* data, size_t hs_len,
DataBuffer* out, uint64_t seq_num) {
DataBuffer* out,
uint64_t seq_num) const {
return MakeHandshakeMessageFragment(hs_type, data, hs_len, out, seq_num, 0,
0);
}
void TlsAgentTestBase::MakeHandshakeMessageFragment(
uint8_t hs_type, const uint8_t* data, size_t hs_len, DataBuffer* out,
uint64_t seq_num, uint32_t fragment_offset, uint32_t fragment_length) {
uint64_t seq_num, uint32_t fragment_offset,
uint32_t fragment_length) const {
size_t index = 0;
if (!fragment_length) fragment_length = hs_len;
index = out->Write(index, hs_type, 1); // Handshake record type.

Просмотреть файл

@ -141,7 +141,7 @@ class TlsAgent : public PollTarget {
void EnableCompression();
void SetDowngradeCheckVersion(uint16_t version);
void CheckSecretsDestroyed();
void ConfigNamedGroup(SSLNamedGroup group, bool en);
void ConfigNamedGroups(const SSLNamedGroup* groups, size_t num);
const std::string& name() const { return name_; }
@ -156,7 +156,7 @@ class TlsAgent : public PollTarget {
const char* state_str() const { return state_str(state()); }
const char* state_str(State state) const { return states[state]; }
static const char* state_str(State state) { return states[state]; }
PRFileDesc* ssl_fd() { return ssl_fd_; }
DummyPrSocket* adapter() { return adapter_; }
@ -213,13 +213,7 @@ class TlsAgent : public PollTarget {
private:
const static char* states[];
void SetState(State state) {
if (state_ == state) return;
LOG("Changing state from " << state_str(state_) << " to "
<< state_str(state));
state_ = state;
}
void SetState(State state);
// Dummy auth certificate hook.
static SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd,
@ -340,6 +334,11 @@ class TlsAgent : public PollTarget {
SniCallbackFunction sni_callback_;
};
inline std::ostream& operator<<(std::ostream& stream,
const TlsAgent::State& state) {
return stream << TlsAgent::state_str(state);
}
class TlsAgentTestBase : public ::testing::Test {
public:
static ::testing::internal::ParamGenerator<std::string> kTlsRolesAll;
@ -355,17 +354,17 @@ class TlsAgentTestBase : public ::testing::Test {
void SetUp();
void TearDown();
void MakeRecord(uint8_t type, uint16_t version, const uint8_t* buf,
size_t len, DataBuffer* out, uint64_t seq_num = 0);
static void MakeRecord(Mode mode, uint8_t type, uint16_t version,
const uint8_t* buf, size_t len, DataBuffer* out,
uint64_t seq_num = 0);
void MakeRecord(uint8_t type, uint16_t version, const uint8_t* buf,
size_t len, DataBuffer* out, uint64_t seq_num = 0) const;
void MakeHandshakeMessage(uint8_t hs_type, const uint8_t* data, size_t hs_len,
DataBuffer* out, uint64_t seq_num = 0);
DataBuffer* out, uint64_t seq_num = 0) const;
void MakeHandshakeMessageFragment(uint8_t hs_type, const uint8_t* data,
size_t hs_len, DataBuffer* out,
uint64_t seq_num, uint32_t fragment_offset,
uint32_t fragment_length);
uint32_t fragment_length) const;
static void MakeTrivialHandshakeRecord(uint8_t hs_type, size_t hs_len,
DataBuffer* out);
static inline TlsAgent::Role ToRole(const std::string& str) {

Просмотреть файл

@ -11,6 +11,7 @@ extern "C" {
#include <iostream>
#include "databuffer.h"
#include "gtest_utils.h"
#include "sslproto.h"
@ -120,6 +121,39 @@ TlsConnectTestBase::TlsConnectTestBase(Mode mode, uint16_t version)
TlsConnectTestBase::~TlsConnectTestBase() {}
// Check the group of each of the supported groups
void TlsConnectTestBase::CheckGroups(
const DataBuffer& groups, std::function<void(SSLNamedGroup)> check_group) {
DuplicateGroupChecker group_set;
uint32_t tmp = 0;
EXPECT_TRUE(groups.Read(0, 2, &tmp));
EXPECT_EQ(groups.len() - 2, static_cast<size_t>(tmp));
for (size_t i = 2; i < groups.len(); i += 2) {
EXPECT_TRUE(groups.Read(i, 2, &tmp));
SSLNamedGroup group = static_cast<SSLNamedGroup>(tmp);
group_set.AddAndCheckGroup(group);
check_group(group);
}
}
// Check the group of each of the shares
void TlsConnectTestBase::CheckShares(
const DataBuffer& shares, std::function<void(SSLNamedGroup)> check_group) {
DuplicateGroupChecker group_set;
uint32_t tmp = 0;
EXPECT_TRUE(shares.Read(0, 2, &tmp));
EXPECT_EQ(shares.len() - 2, static_cast<size_t>(tmp));
size_t i;
for (i = 2; i < shares.len(); i += 4 + tmp) {
ASSERT_TRUE(shares.Read(i, 2, &tmp));
SSLNamedGroup group = static_cast<SSLNamedGroup>(tmp);
group_set.AddAndCheckGroup(group);
check_group(group);
ASSERT_TRUE(shares.Read(i + 2, 2, &tmp));
}
EXPECT_EQ(shares.len(), i);
}
void TlsConnectTestBase::ClearStats() {
// Clear statistics.
SSL3Statistics* stats = SSL_GetStatistics();
@ -344,23 +378,27 @@ void TlsConnectTestBase::ConfigureSessionCache(SessionResumptionMode client,
void TlsConnectTestBase::CheckResumption(SessionResumptionMode expected) {
EXPECT_NE(RESUME_BOTH, expected);
int resume_ct = expected ? 1 : 0;
int stateless_ct = (expected & RESUME_TICKET) ? 1 : 0;
int resume_count = expected ? 1 : 0;
int stateless_count = (expected & RESUME_TICKET) ? 1 : 0;
// Note: hch == server counter; hsh == client counter.
SSL3Statistics* stats = SSL_GetStatistics();
EXPECT_EQ(resume_ct, stats->hch_sid_cache_hits);
EXPECT_EQ(resume_ct, stats->hsh_sid_cache_hits);
EXPECT_EQ(resume_count, stats->hch_sid_cache_hits);
EXPECT_EQ(resume_count, stats->hsh_sid_cache_hits);
EXPECT_EQ(stateless_ct, stats->hch_sid_stateless_resumes);
EXPECT_EQ(stateless_ct, stats->hsh_sid_stateless_resumes);
EXPECT_EQ(stateless_count, stats->hch_sid_stateless_resumes);
EXPECT_EQ(stateless_count, stats->hsh_sid_stateless_resumes);
if (resume_ct && client_->version() < SSL_LIBRARY_VERSION_TLS_1_3) {
// Check that the last two session ids match.
// TLS 1.3 doesn't do session id-based resumption. It's all
// tickets.
EXPECT_EQ(2U, session_ids_.size());
EXPECT_EQ(session_ids_[session_ids_.size() - 1],
session_ids_[session_ids_.size() - 2]);
if (expected != RESUME_NONE) {
if (client_->version() < SSL_LIBRARY_VERSION_TLS_1_3) {
// Check that the last two session ids match.
ASSERT_EQ(2U, session_ids_.size());
EXPECT_EQ(session_ids_[session_ids_.size() - 1],
session_ids_[session_ids_.size() - 2]);
} else {
// TLS 1.3 only uses tickets.
EXPECT_TRUE(expected & RESUME_TICKET);
}
}
}
@ -385,11 +423,6 @@ void TlsConnectTestBase::EnsureModelSockets() {
// Initialise agents.
ASSERT_TRUE(client_model_->Init());
ASSERT_TRUE(server_model_->Init());
// Set desired properties on the models.
// For now only ALPN.
client_model_->EnableAlpn(alpn_dummy_val_, sizeof(alpn_dummy_val_));
server_model_->EnableAlpn(alpn_dummy_val_, sizeof(alpn_dummy_val_));
}
void TlsConnectTestBase::CheckAlpn(const std::string& val) {

Просмотреть файл

@ -73,6 +73,10 @@ class TlsConnectTestBase : public ::testing::Test {
void ConnectWithCipherSuite(uint16_t cipher_suite);
void CheckKeys(SSLKEAType kea_type, SSLAuthType auth_type,
size_t kea_size = 0) const;
void CheckGroups(const DataBuffer& groups,
std::function<void(SSLNamedGroup)> check_group);
void CheckShares(const DataBuffer& shares,
std::function<void(SSLNamedGroup)> check_group);
void SetExpectedVersion(uint16_t version);
// Expect resumption of a particular type.
@ -122,6 +126,19 @@ class TlsConnectTestBase : public ::testing::Test {
bool expect_extended_master_secret_;
bool expect_early_data_accepted_;
// Track groups and make sure that there are no duplicates.
class DuplicateGroupChecker {
public:
void AddAndCheckGroup(SSLNamedGroup group) {
EXPECT_EQ(groups_.end(), groups_.find(group))
<< "Group " << group << " should not be duplicated";
groups_.insert(group);
}
private:
std::set<SSLNamedGroup> groups_;
};
};
// A non-parametrized TLS test base.

Просмотреть файл

@ -464,4 +464,12 @@ PacketFilter::Action TlsInspectorClientHelloVersionChanger::FilterHandshake(
return KEEP;
}
PacketFilter::Action SelectiveDropFilter::Filter(const DataBuffer& input,
DataBuffer* output) {
if (counter_ >= 32) {
return KEEP;
}
return ((1 << counter_++) & pattern_) ? DROP : KEEP;
}
} // namespace nss_test

Просмотреть файл

@ -223,10 +223,12 @@ class TlsExtensionCapture : public TlsExtensionFilter {
public:
TlsExtensionCapture(uint16_t ext) : extension_(ext), data_() {}
const DataBuffer& extension() const { return data_; }
protected:
virtual PacketFilter::Action FilterExtension(uint16_t extension_type,
const DataBuffer& input,
DataBuffer* output);
const DataBuffer& extension() const { return data_; }
private:
const uint16_t extension_;
@ -281,6 +283,21 @@ class TlsInspectorClientHelloVersionChanger : public TlsHandshakeFilter {
TlsAgent* server_;
};
// This class selectively drops complete writes. This relies on the fact that
// writes in libssl are on record boundaries.
class SelectiveDropFilter : public PacketFilter {
public:
SelectiveDropFilter(uint32_t pattern) : pattern_(pattern), counter_(0) {}
protected:
virtual PacketFilter::Action Filter(const DataBuffer& input,
DataBuffer* output) override;
private:
const uint32_t pattern_;
uint8_t counter_;
};
} // namespace nss_test
#endif

Просмотреть файл

@ -26,6 +26,7 @@ const uint8_t kTlsApplicationDataType = 23;
const uint8_t kTlsHandshakeClientHello = 1;
const uint8_t kTlsHandshakeServerHello = 2;
const uint8_t kTlsHandshakeHelloRetryRequest = 6;
const uint8_t kTlsHandshakeEncryptedExtensions = 8;
const uint8_t kTlsHandshakeCertificate = 11;
const uint8_t kTlsHandshakeServerKeyExchange = 12;
@ -46,7 +47,8 @@ const uint8_t kTlsAlertMissingExtension = 109;
const uint8_t kTlsAlertUnsupportedExtension = 110;
const uint8_t kTlsAlertNoApplicationProtocol = 120;
const uint8_t kTlsExtensionPreSharedKey = 41;
const uint16_t kTlsSigSchemeRsaPkcs1Sha1 = 0x0201;
const uint16_t kTlsSigSchemeRsaPssSha256 = 0x0700;
const uint8_t kTlsFakeChangeCipherSpec[] = {
kTlsChangeCipherSpecType, // Type

Просмотреть файл

@ -2195,6 +2195,10 @@ SetRequestExts(void *object, CERTCertExtension **exts)
request->tbsRequest->requestExtensions = exts;
}
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvarargs"
#endif
SECStatus
CERT_AddOCSPAcceptableResponses(CERTOCSPRequest *request,
SECOidTag responseType0, ...)
@ -2261,6 +2265,9 @@ loser:
(void)CERT_FinishExtensions(extHandle);
return rv;
}
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
/*
* FUNCTION: CERT_DestroyOCSPRequest

Просмотреть файл

@ -487,3 +487,12 @@ ER3(SSL_ERROR_MISSING_SUPPORTED_GROUPS, (SSL_ERROR_BASE + 152),
ER3(SSL_ERROR_TOO_MANY_RECORDS, (SSL_ERROR_BASE + 153),
"SSL sent or received too many records with the same symmetric key.")
ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_RETRY_REQUEST, (SSL_ERROR_BASE + 154),
"SSL received an unexpected Hello Retry Request handshake message.")
ER3(SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST, (SSL_ERROR_BASE + 155),
"SSL received a malformed Hello Retry Request handshake message.")
ER3(SSL_ERROR_BAD_2ND_CLIENT_HELLO, (SSL_ERROR_BASE + 156),
"SSL received a second Client Hello message without a usable key share.")

Просмотреть файл

@ -790,9 +790,7 @@ SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey,
if (requiredECCbits > signatureKeyStrength)
requiredECCbits = signatureKeyStrength;
ecGroup =
ssl_GetECGroupWithStrength(PR_UINT32_MAX,
requiredECCbits);
ecGroup = ssl_GetECGroupWithStrength(NULL, requiredECCbits);
rv = ssl_NamedGroup2ECParams(NULL, ecGroup, &ecParams);
if (rv == SECFailure) {
break;

Просмотреть файл

@ -946,7 +946,11 @@ dtls_FinishedTimerCb(sslSocket *ss)
void
dtls_RehandshakeCleanup(sslSocket *ss)
{
PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3);
/* Skip this if we are handling a second ClientHello. */
if (ss->ssl3.hs.helloRetry) {
return;
}
PORT_Assert((ss->version < SSL_LIBRARY_VERSION_TLS_1_3));
dtls_CancelTimer(ss);
ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE);
ss->ssl3.hs.sendMessageSeq = 0;
@ -1039,7 +1043,7 @@ dtls_HandleHelloVerifyRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ssl_GetXmitBufLock(ss); /*******************************/
/* Now re-send the client hello */
rv = ssl3_SendClientHello(ss, PR_TRUE);
rv = ssl3_SendClientHello(ss, client_hello_retransmit);
ssl_ReleaseXmitBufLock(ss); /*******************************/
@ -1189,14 +1193,16 @@ DTLS_GetHandshakeTimeout(PRFileDesc *socket, PRIntervalTime *timeout)
* and sets |*seqNum| to the packet sequence number.
*/
PRBool
dtls_IsRelevant(sslSocket *ss, const ssl3CipherSpec *crSpec,
const SSL3Ciphertext *cText, sslSequenceNumber *seqNum)
dtls_IsRelevant(sslSocket *ss, const SSL3Ciphertext *cText,
PRBool *sameEpoch, PRUint64 *seqNum)
{
const ssl3CipherSpec *crSpec = ss->ssl3.crSpec;
DTLSEpoch epoch;
sslSequenceNumber dtls_seq_num;
epoch = cText->seq_num >> 48;
if (crSpec->epoch != epoch) {
*sameEpoch = crSpec->epoch == epoch;
if (!*sameEpoch) {
SSL_DBG(("%d: SSL3[%d]: dtls_IsRelevant, received packet "
"from irrelevant epoch %d",
SSL_GETPID(), ss->fd, epoch));
@ -1229,11 +1235,17 @@ dtls_IsRelevant(sslSocket *ss, const ssl3CipherSpec *crSpec,
* dropped because it has the same epoch that the client currently expects.
*/
SECStatus
dtls_MaybeRetransmitHandshake(sslSocket *ss, const SSL3Ciphertext *cText)
dtls_MaybeRetransmitHandshake(sslSocket *ss, const SSL3Ciphertext *cText,
PRBool sameEpoch)
{
SECStatus rv = SECSuccess;
DTLSEpoch messageEpoch = cText->seq_num >> 48;
/* Drop messages from other epochs if we are ignoring things. */
if (!sameEpoch && ss->ssl3.hs.zeroRttIgnore != ssl_0rtt_ignore_none) {
return SECSuccess;
}
if (!ss->sec.isServer && ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 &&
messageEpoch == 0 && cText->type == content_handshake) {
ssl_GetSSL3HandshakeLock(ss);

Просмотреть файл

@ -208,7 +208,7 @@ SSL_ConfigServerCert;
;+};
;+NSS_3.27 { # NSS 3.27 release
;+ global:
SSL_NamedGroupPrefSet;
SSL_NamedGroupConfig;
;+ local:
;+*;
;+};

Просмотреть файл

@ -216,7 +216,7 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
* enabled. A server will only negotiate TLS_DHE_* cipher suites if the
* client includes the extension.
*
* See SSL_NamedGroupPrefSet() for how to control which groups are enabled.
* See SSL_NamedGroupConfig() for how to control which groups are enabled.
*
* This option cannot be enabled if NSS is not compiled with ECC support.
*/
@ -392,16 +392,16 @@ SSL_IMPORT SECStatus SSL_SignaturePrefGet(
SSL_IMPORT unsigned int SSL_SignatureMaxCount();
/*
** Enable or disable a named group (see SSLNamedGroup). This includes both EC
** and FF groups using in Diffie-Hellman key exchange, as well as the EC groups
** used in ECDSA signatures. By default libssl enables all supported groups.
** NSS uses its own preferences to select a group though it will select the
** first group from SSL_DHEGroupPrefSet if that was called.
** Define custom priorities for EC and FF groups used in DH key exchange and EC
** groups for ECDSA. This only changes the order of enabled lists (and thus
** their priorities) and enables all groups in |groups| while disabling all other
** groups.
*/
SSL_IMPORT SECStatus SSL_NamedGroupPrefSet(PRFileDesc *fd, SSLNamedGroup group,
PRBool enable);
SSL_IMPORT SECStatus SSL_NamedGroupConfig(PRFileDesc *fd,
const SSLNamedGroup *groups,
unsigned int num_groups);
/* Deprecated: use SSL_NamedGroupPrefSet() instead.
/* Deprecated: use SSL_NamedGroupConfig() instead.
** SSL_DHEGroupPrefSet is used to configure the set of allowed/enabled DHE group
** parameters that can be used by NSS for the given server socket.
** The first item in the array is used as the default group, if no other
@ -432,11 +432,11 @@ SSL_IMPORT SECStatus SSL_DHEGroupPrefSet(PRFileDesc *fd,
** on sockets. The function needs to be called again for every socket that
** should use the weak group.
**
** It is allowed to use this API in combination with the SSL_NamedGroupPrefSet API.
** If both APIs have been called, the weakest group will be used,
** unless it is certain that the client supports larger group parameters.
** The weak group will be used as the default group, overriding the preference
** for the first group potentially set with a call to SSL_DHEGroupPrefSet.
** It is allowed to use this API in combination with the SSL_NamedGroupConfig API.
** If both APIs have been called, the weakest group will be used, unless it is
** certain that the client supports larger group parameters. The weak group will
** be used as the default group for TLS <= 1.2, overriding the preference for
** the first group potentially set with a call to SSL_NamedGroupConfig.
*/
SSL_IMPORT SECStatus SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enabled);

Просмотреть файл

@ -81,6 +81,10 @@ static SECStatus ssl3_AESGCMBypass(ssl3KeyMaterial *keys, PRBool doDecrypt,
int additionalDataLen);
#endif
static CK_MECHANISM_TYPE ssl3_GetHashMechanismByHashType(SSLHashType hashType);
static CK_MECHANISM_TYPE ssl3_GetMgfMechanismByHashType(SSLHashType hash);
PRBool ssl_IsRsaPssSignatureScheme(SignatureScheme scheme);
#define MAX_SEND_BUF_LENGTH 32000 /* watch for 16-bit integer overflow */
#define MIN_SEND_BUF_LENGTH 4000
@ -210,10 +214,9 @@ static const SignatureScheme defaultSignatureSchemes[] = {
ssl_sig_ecdsa_secp384r1_sha384,
ssl_sig_ecdsa_secp521r1_sha512,
ssl_sig_ecdsa_sha1,
/* bug 1280439 will restore these */
/* ssl_sig_rsa_pss_sha256,
ssl_sig_rsa_pss_sha384,
ssl_sig_rsa_pss_sha512, */
ssl_sig_rsa_pss_sha256,
ssl_sig_rsa_pss_sha384,
ssl_sig_rsa_pss_sha512,
ssl_sig_rsa_pkcs1_sha256,
ssl_sig_rsa_pkcs1_sha384,
ssl_sig_rsa_pkcs1_sha512,
@ -344,9 +347,6 @@ static const ssl3BulkCipherDef bulk_cipher_defs[] = {
{cipher_missing, calg_null, 0, 0, type_stream, 0, 0, 0, 0,
SEC_OID_UNKNOWN, "missing", 0U},
};
#undef MR_MAX
#undef MR_128
#undef MR_LOW
static const ssl3KEADef kea_defs[] =
{ /* indexed by SSL3KeyExchangeAlgorithm */
@ -622,6 +622,9 @@ ssl3_DecodeHandshakeType(int msgType)
case new_session_ticket:
rv = "session_ticket (4)";
break;
case hello_retry_request:
rv = "hello_retry_request (6)";
break;
case encrypted_extensions:
rv = "encrypted_extensions (8)";
break;
@ -835,9 +838,10 @@ static PRBool
ssl_NamedGroupTypeEnabled(const sslSocket *ss, NamedGroupType groupType)
{
unsigned int i;
for (i = 0; i < ssl_named_group_count; ++i) {
if (ssl_named_groups[i].type == groupType &&
ssl_NamedGroupEnabled(ss, &ssl_named_groups[i])) {
for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
if (ss->namedGroupPreferences[i] &&
ss->namedGroupPreferences[i]->type == groupType &&
ssl_NamedGroupEnabled(ss, ss->namedGroupPreferences[i])) {
return PR_TRUE;
}
}
@ -861,6 +865,11 @@ ssl_KEAEnabled(const sslSocket *ss, SSLKEAType keaType)
* earlier and named groups aren't required. */
if (!ss->opt.requireDHENamedGroups &&
ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
/* If the client indicates support for named FFDHE groups, check
* that we have one in common. */
if (ss->sec.isServer && ss->ssl3.hs.peerSupportsFfdheGroups) {
return ssl_NamedGroupTypeEnabled(ss, group_type_ff);
}
return PR_TRUE;
}
/* If the server requires the extension, then the client must have
@ -1150,12 +1159,13 @@ ssl3_GetNewRandom(SSL3Random *random)
/* Called by ssl3_SendServerKeyExchange and ssl3_SendCertificateVerify */
SECStatus
ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf,
PRBool isTLS)
ssl3_SignHashes(sslSocket *ss, SSL3Hashes *hash, SECKEYPrivateKey *key,
SECItem *buf)
{
SECStatus rv = SECFailure;
PRBool doDerEncode = PR_FALSE;
int signatureLen;
PRBool isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
PRBool useRsaPss = ssl_IsRsaPssSignatureScheme(ss->ssl3.hs.signatureScheme);
SECItem hashItem;
buf->data = NULL;
@ -1195,8 +1205,16 @@ ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf,
}
PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len));
if (hash->hashAlg == ssl_hash_none) {
signatureLen = PK11_SignatureLen(key);
if (useRsaPss || hash->hashAlg == ssl_hash_none) {
CK_MECHANISM_TYPE mech = PK11_MapSignKeyType(key->keyType);
int signatureLen = PK11_SignatureLen(key);
SECItem *params = NULL;
CK_RSA_PKCS_PSS_PARAMS pssParams;
SECItem pssParamsItem = { siBuffer,
(unsigned char *)&pssParams,
sizeof(pssParams) };
if (signatureLen <= 0) {
PORT_SetError(SEC_ERROR_INVALID_KEY);
goto done;
@ -1207,7 +1225,15 @@ ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf,
if (!buf->data)
goto done; /* error code was set. */
rv = PK11_Sign(key, buf, &hashItem);
if (useRsaPss) {
pssParams.hashAlg = ssl3_GetHashMechanismByHashType(hash->hashAlg);
pssParams.mgf = ssl3_GetMgfMechanismByHashType(hash->hashAlg);
pssParams.sLen = hashItem.len;
params = &pssParamsItem;
mech = CKM_RSA_PKCS_PSS;
}
rv = PK11_SignWithMechanism(key, mech, params, buf, &hashItem);
} else {
SECOidTag hashOID = ssl3_HashTypeToOID(hash->hashAlg);
rv = SGN_Digest(key, hashOID, buf, &hashItem);
@ -1238,8 +1264,8 @@ done:
/* Called from ssl3_HandleServerKeyExchange, ssl3_HandleCertificateVerify */
SECStatus
ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert,
SECItem *buf, PRBool isTLS, void *pwArg)
ssl3_VerifySignedHashes(sslSocket *ss, SignatureScheme scheme, SSL3Hashes *hash,
SECItem *buf)
{
SECKEYPublicKey *key;
SECItem *signature = NULL;
@ -1247,11 +1273,13 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert,
SECItem hashItem;
SECOidTag encAlg;
SECOidTag hashAlg;
void *pwArg = ss->pkcs11PinArg;
PRBool isRsaPssScheme = ssl_IsRsaPssSignatureScheme(scheme);
PRINT_BUF(60, (NULL, "check signed hashes",
buf->data, buf->len));
key = CERT_ExtractPublicKey(cert);
key = CERT_ExtractPublicKey(ss->sec.peerCert);
if (key == NULL) {
ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
return SECFailure;
@ -1276,7 +1304,8 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert,
hashItem.len = hash->len;
}
/* Allow DER encoded DSA signatures in SSL 3.0 */
if (isTLS || buf->len != SECKEY_SignatureLen(key)) {
if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0 ||
buf->len != SECKEY_SignatureLen(key)) {
signature = DSAU_DecodeDerSigToLen(buf, SECKEY_SignatureLen(key));
if (!signature) {
PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
@ -1313,13 +1342,31 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert,
PRINT_BUF(60, (NULL, "hash(es) to be verified",
hashItem.data, hashItem.len));
if (hashAlg == SEC_OID_UNKNOWN || SECKEY_GetPublicKeyType(key) == dsaKey) {
if (isRsaPssScheme ||
hashAlg == SEC_OID_UNKNOWN ||
SECKEY_GetPublicKeyType(key) == dsaKey) {
/* VFY_VerifyDigestDirect requires DSA signatures to be DER-encoded.
* DSA signatures are DER-encoded in TLS but not in SSL3 and the code
* above always removes the DER encoding of DSA signatures when
* present. Thus DSA signatures are always verified with PK11_Verify.
*/
rv = PK11_Verify(key, buf, &hashItem, pwArg);
CK_MECHANISM_TYPE mech = PK11_MapSignKeyType(key->keyType);
SECItem *params = NULL;
CK_RSA_PKCS_PSS_PARAMS pssParams;
SECItem pssParamsItem = { siBuffer,
(unsigned char *)&pssParams,
sizeof(pssParams) };
if (isRsaPssScheme) {
pssParams.hashAlg = ssl3_GetHashMechanismByHashType(hash->hashAlg);
pssParams.mgf = ssl3_GetMgfMechanismByHashType(hash->hashAlg);
pssParams.sLen = hashItem.len;
params = &pssParamsItem;
mech = CKM_RSA_PKCS_PSS;
}
rv = PK11_VerifyWithMechanism(key, mech, params, buf, &hashItem, pwArg);
} else {
rv = VFY_VerifyDigestDirect(&hashItem, key, buf, encAlg, hashAlg,
pwArg);
@ -1480,17 +1527,18 @@ ssl3_ComputeDHKeyHash(sslSocket *ss, SSLHashType hashAlg, SSL3Hashes *hashes,
PRUint8 *hashBuf;
PRUint8 *pBuf;
SECStatus rv = SECSuccess;
unsigned int bufLen;
unsigned int bufLen, yLen;
PRUint8 buf[2 * SSL3_RANDOM_LENGTH + 2 + 4096 / 8 + 2 + 4096 / 8];
PORT_Assert(dh_p.data);
PORT_Assert(dh_g.data);
PORT_Assert(dh_Ys.data);
yLen = padY ? dh_p.len : dh_Ys.len;
bufLen = 2 * SSL3_RANDOM_LENGTH +
2 + dh_p.len +
2 + dh_g.len +
2 + (padY ? dh_p.len : dh_Ys.len);
2 + yLen;
if (bufLen <= sizeof buf) {
hashBuf = buf;
} else {
@ -1504,19 +1552,13 @@ ssl3_ComputeDHKeyHash(sslSocket *ss, SSLHashType hashAlg, SSL3Hashes *hashes,
pBuf = hashBuf + SSL3_RANDOM_LENGTH;
memcpy(pBuf, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH);
pBuf += SSL3_RANDOM_LENGTH;
pBuf[0] = (PRUint8)(dh_p.len >> 8);
pBuf[1] = (PRUint8)(dh_p.len);
pBuf += 2;
pBuf = ssl_EncodeUintX(dh_p.len, 2, pBuf);
memcpy(pBuf, dh_p.data, dh_p.len);
pBuf += dh_p.len;
pBuf[0] = (PRUint8)(dh_g.len >> 8);
pBuf[1] = (PRUint8)(dh_g.len);
pBuf += 2;
pBuf = ssl_EncodeUintX(dh_g.len, 2, pBuf);
memcpy(pBuf, dh_g.data, dh_g.len);
pBuf += dh_g.len;
pBuf[0] = (PRUint8)(dh_p.len >> 8);
pBuf[1] = (PRUint8)(dh_p.len);
pBuf += 2;
pBuf = ssl_EncodeUintX(yLen, 2, pBuf);
if (padY && dh_p.len > dh_Ys.len) {
memset(pBuf, 0, dh_p.len - dh_Ys.len);
pBuf += dh_p.len - dh_Ys.len;
@ -3475,11 +3517,10 @@ ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
if ((flags & ~allowedFlags) != 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
} else {
count = ssl3_SendRecord(ss, NULL, content_handshake,
ss->sec.ci.sendBuf.buf,
ss->sec.ci.sendBuf.len, flags);
}
count = ssl3_SendRecord(ss, NULL, content_handshake,
ss->sec.ci.sendBuf.buf,
ss->sec.ci.sendBuf.len, flags);
if (count < 0) {
int err = PORT_GetError();
PORT_Assert(err != PR_WOULD_BLOCK_ERROR);
@ -3852,10 +3893,6 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf)
return SECFailure;
}
if (desc == end_of_early_data) {
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
PORT_SetError(error);
return SECFailure;
}
return tls13_HandleEndOfEarlyData(ss);
}
if ((desc == no_certificate) && (ss->ssl3.hs.ws == wait_client_cert)) {
@ -4012,6 +4049,22 @@ ssl3_HandleChangeCipherSpecs(sslSocket *ss, sslBuffer *buf)
return SECSuccess;
}
static CK_MECHANISM_TYPE
ssl3_GetMgfMechanismByHashType(SSLHashType hash)
{
switch (hash) {
case ssl_hash_sha256:
return CKG_MGF1_SHA256;
case ssl_hash_sha384:
return CKG_MGF1_SHA384;
case ssl_hash_sha512:
return CKG_MGF1_SHA512;
default:
PORT_Assert(0);
}
return CKG_MGF1_SHA256;
}
/* Function valid for >= TLS 1.2, only. */
static CK_MECHANISM_TYPE
ssl3_GetHashMechanismByHashType(SSLHashType hashType)
@ -5145,6 +5198,9 @@ ssl_IsSupportedSignatureScheme(SignatureScheme scheme)
case ssl_sig_rsa_pkcs1_sha256:
case ssl_sig_rsa_pkcs1_sha384:
case ssl_sig_rsa_pkcs1_sha512:
case ssl_sig_rsa_pss_sha256:
case ssl_sig_rsa_pss_sha384:
case ssl_sig_rsa_pss_sha512:
case ssl_sig_ecdsa_secp256r1_sha256:
case ssl_sig_ecdsa_secp384r1_sha384:
case ssl_sig_ecdsa_secp521r1_sha512:
@ -5155,10 +5211,6 @@ ssl_IsSupportedSignatureScheme(SignatureScheme scheme)
case ssl_sig_ecdsa_sha1:
return PR_TRUE;
case ssl_sig_rsa_pss_sha256:
case ssl_sig_rsa_pss_sha384:
case ssl_sig_rsa_pss_sha512:
/* Bug 1280439 will add PSS. */
case ssl_sig_none:
case ssl_sig_ed25519:
case ssl_sig_ed448:
@ -5167,6 +5219,21 @@ ssl_IsSupportedSignatureScheme(SignatureScheme scheme)
return PR_FALSE;
}
PRBool
ssl_IsRsaPssSignatureScheme(SignatureScheme scheme)
{
switch (scheme) {
case ssl_sig_rsa_pss_sha256:
case ssl_sig_rsa_pss_sha384:
case ssl_sig_rsa_pss_sha512:
return PR_TRUE;
default:
return PR_FALSE;
}
return PR_FALSE;
}
/* ssl_ConsumeSignatureScheme reads a SignatureScheme (formerly
* SignatureAndHashAlgorithm) structure from |b| and puts the resulting value
* into |out|. |b| and |length| are updated accordingly.
@ -5575,13 +5642,40 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss,
* Begin Send and Handle functions for handshakes.
**************************************************************************/
#ifdef TRACE
#define CHTYPE(t) \
case client_hello_##t: \
return #t;
static const char *
ssl_ClientHelloTypeName(sslClientHelloType type)
{
switch (type) {
CHTYPE(initial);
CHTYPE(retry);
CHTYPE(retransmit); /* DTLS only */
CHTYPE(renegotiation); /* TLS <= 1.2 only */
}
PORT_Assert(0);
return NULL;
}
#undef CHTYPE
#endif
/* Called from ssl3_HandleHelloRequest(),
* ssl3_RedoHandshake()
* ssl_BeginClientHandshake (when resuming ssl3 session)
* dtls_HandleHelloVerifyRequest(with resending=PR_TRUE)
*
* The |type| argument indicates what is going on here:
* - client_hello_initial is set for the very first ClientHello
* - client_hello_retry indicates that this is a second attempt after receiving
* a HelloRetryRequest (in TLS 1.3)
* - client_hello_retransmit is used in DTLS when resending
* - client_hello_renegotiation is used to renegotiate (in TLS <1.3)
*/
SECStatus
ssl3_SendClientHello(sslSocket *ss, PRBool resending)
ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
{
sslSessionID *sid;
ssl3CipherSpec *cwSpec;
@ -5595,41 +5689,43 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
PRInt32 total_exten_len = 0;
unsigned paddingExtensionLen;
unsigned numCompressionMethods;
PRInt32 flags;
SSL_TRC(3, ("%d: SSL3[%d]: send client_hello handshake", SSL_GETPID(),
ss->fd));
SSL_TRC(3, ("%d: SSL3[%d]: send %s ClientHello handshake", SSL_GETPID(),
ss->fd, ssl_ClientHelloTypeName(type)));
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
rv = ssl3_InitState(ss);
if (rv != SECSuccess) {
return rv; /* ssl3_InitState has set the error code. */
/* If we are responding to a HelloRetryRequest, don't reinitialize. We need
* to maintain the handshake hashes. */
if (ss->ssl3.hs.helloRetry) {
PORT_Assert(type == client_hello_retry);
} else {
rv = ssl3_InitState(ss);
if (rv != SECSuccess) {
return rv; /* ssl3_InitState has set the error code. */
}
rv = ssl3_RestartHandshakeHashes(ss);
if (rv != SECSuccess) {
return rv;
}
}
/* These must be reset every handshake. */
ss->ssl3.hs.sendingSCSV = PR_FALSE;
ss->ssl3.hs.preliminaryInfo = 0;
PORT_Assert(IS_DTLS(ss) || !resending);
PORT_Assert(IS_DTLS(ss) || type != client_hello_retransmit);
SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE);
ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE;
/* We might be starting a session renegotiation in which case we should
* clear previous state.
*/
PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData));
rv = ssl3_RestartHandshakeHashes(ss);
if (rv != SECSuccess) {
return rv;
}
/*
* During a renegotiation, ss->clientHelloVersion will be used again to
* work around a Windows SChannel bug. Ensure that it is still enabled.
*/
if (ss->firstHsDone) {
PORT_Assert(type != client_hello_initial);
if (SSL_ALL_VERSIONS_DISABLED(&ss->vrange)) {
PORT_SetError(SSL_ERROR_SSL_DISABLED);
return SECFailure;
@ -5776,7 +5872,8 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
}
}
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3 &&
type == client_hello_initial) {
rv = tls13_SetupClientHello(ss);
if (rv != SECSuccess) {
if (sid) {
@ -5934,7 +6031,8 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
return rv; /* err set by ssl3_AppendHandshake* */
}
if (!resending) { /* Don't re-generate if we are in DTLS re-sending mode */
/* Generate a new random if this is the first attempt. */
if (type == client_hello_initial) {
rv = ssl3_GetNewRandom(&ss->ssl3.hs.client_random);
if (rv != SECSuccess) {
if (sid->u.ssl3.lock) {
@ -6108,14 +6206,6 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
ssl_renegotiation_info_xtn;
}
flags = 0;
if (!ss->firstHsDone && !IS_DTLS(ss)) {
flags |= ssl_SEND_FLAG_CAP_RECORD_VERSION;
}
rv = ssl3_FlushHandshake(ss, flags);
if (rv != SECSuccess) {
return rv; /* error code set by ssl3_FlushHandshake */
}
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
rv = tls13_MaybeDo0RTTHandshake(ss);
if (rv != SECSuccess) {
@ -6123,6 +6213,31 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
}
}
/* On TLS (but not DTLS), if we sent 0-RTT, then we will have data in the
* pending buffer. This just pushes a little of that out. If we didn't do
* that, we wouldn't send a ClientHello the first time and applications
* would have to push SSL_ForceHandshake() twice. This should go away once
* we have Finished stuffed in the ClientHello. */
if (!IS_DTLS(ss) && ss->ssl3.hs.zeroRttState == ssl_0rtt_sent) {
int sent;
PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
PORT_Assert(ss->pendingBuf.len);
sent = ssl_SendSavedWriteData(ss);
if (sent < 0) {
return SECFailure;
}
} else {
PRInt32 flags = 0;
if (!ss->firstHsDone && !IS_DTLS(ss)) {
flags |= ssl_SEND_FLAG_CAP_RECORD_VERSION;
}
rv = ssl3_FlushHandshake(ss, flags);
if (rv != SECSuccess) {
return rv; /* error code set by ssl3_FlushHandshake */
}
}
ss->ssl3.hs.ws = wait_server_hello;
return SECSuccess;
}
@ -6169,7 +6284,7 @@ ssl3_HandleHelloRequest(sslSocket *ss)
}
ssl_GetXmitBufLock(ss);
rv = ssl3_SendClientHello(ss, PR_FALSE);
rv = ssl3_SendClientHello(ss, client_hello_renegotiation);
ssl_ReleaseXmitBufLock(ss);
return rv;
@ -7081,7 +7196,6 @@ static SECStatus
ssl3_SendCertificateVerify(sslSocket *ss, SECKEYPrivateKey *privKey)
{
SECStatus rv = SECFailure;
PRBool isTLS;
PRBool isTLS12;
SECItem buf = { siBuffer, NULL, 0 };
SSL3Hashes hashes;
@ -7128,11 +7242,10 @@ ssl3_SendCertificateVerify(sslSocket *ss, SECKEYPrivateKey *privKey)
goto done; /* err code was set by ssl3_ComputeHandshakeHashes */
}
isTLS = (PRBool)(ss->version > SSL_LIBRARY_VERSION_3_0);
isTLS12 = (PRBool)(ss->version == SSL_LIBRARY_VERSION_TLS_1_2);
PORT_Assert(ss->version <= SSL_LIBRARY_VERSION_TLS_1_2);
rv = ssl3_SignHashes(&hashes, privKey, &buf, isTLS);
rv = ssl3_SignHashes(ss, &hashes, privKey, &buf);
if (rv == SECSuccess && !ss->sec.isServer) {
/* Remember the info about the slot that did the signing.
** Later, when doing an SSL restart handshake, verify this.
@ -7266,6 +7379,13 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
}
}
/* We got a HelloRetryRequest, but the server didn't pick 1.3. Scream. */
if (ss->ssl3.hs.helloRetry && version < SSL_LIBRARY_VERSION_TLS_1_3) {
desc = illegal_parameter;
errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
goto alert_loser;
}
rv = ssl3_NegotiateVersion(ss, version, PR_FALSE);
if (rv != SECSuccess) {
desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version
@ -7698,6 +7818,7 @@ ssl_HandleRSAServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SSL3AlertDescription desc = illegal_parameter;
SSLHashType hashAlg;
PRBool isTLS = ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0;
SignatureScheme sigScheme = ssl_sig_none;
SECItem modulus = { siBuffer, NULL, 0 };
SECItem exponent = { siBuffer, NULL, 0 };
@ -7724,8 +7845,6 @@ ssl_HandleRSAServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
goto loser; /* malformed. */
}
if (ss->version == SSL_LIBRARY_VERSION_TLS_1_2) {
SignatureScheme sigScheme;
rv = ssl_ConsumeSignatureScheme(ss, &b, &length, &sigScheme);
if (rv != SECSuccess) {
goto loser; /* malformed or unsupported. */
@ -7766,8 +7885,7 @@ ssl_HandleRSAServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
goto alert_loser;
}
rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
isTLS, ss->pkcs11PinArg);
rv = ssl3_VerifySignedHashes(ss, sigScheme, &hashes, &signature);
if (rv != SECSuccess) {
errCode =
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
@ -7821,6 +7939,7 @@ ssl_HandleDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SSL3AlertDescription desc = illegal_parameter;
SSLHashType hashAlg;
PRBool isTLS = ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0;
SignatureScheme sigScheme;
SECItem dh_p = { siBuffer, NULL, 0 };
SECItem dh_g = { siBuffer, NULL, 0 };
@ -7876,8 +7995,6 @@ ssl_HandleDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
}
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
SignatureScheme sigScheme;
rv = ssl_ConsumeSignatureScheme(ss, &b, &length, &sigScheme);
if (rv != SECSuccess) {
goto loser; /* malformed or unsupported. */
@ -7891,6 +8008,7 @@ ssl_HandleDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
} else {
/* Use ssl_hash_none to represent the MD5+SHA1 combo. */
hashAlg = ssl_hash_none;
sigScheme = ssl_sig_none;
}
rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
if (rv != SECSuccess) {
@ -7921,8 +8039,7 @@ ssl_HandleDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
goto alert_loser;
}
rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
isTLS, ss->pkcs11PinArg);
rv = ssl3_VerifySignedHashes(ss, sigScheme, &hashes, &signature);
if (rv != SECSuccess) {
errCode =
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
@ -8810,7 +8927,8 @@ ssl3_KEASupportsTickets(const ssl3KEADef *kea_def)
** (the server) have TLS 1.1 support enabled.
*/
SECStatus
ssl3_NegotiateCipherSuite(sslSocket *ss, const SECItem *suites)
ssl3_NegotiateCipherSuite(sslSocket *ss, const SECItem *suites,
PRBool initHashes)
{
int j;
int i;
@ -8824,7 +8942,7 @@ ssl3_NegotiateCipherSuite(sslSocket *ss, const SECItem *suites)
for (i = 0; i + 1 < suites->len; i += 2) {
PRUint16 suite_i = (suites->data[i] << 8) | suites->data[i + 1];
if (suite_i == suite->cipher_suite) {
return ssl3_SetCipherSuite(ss, suite_i, PR_TRUE);
return ssl3_SetCipherSuite(ss, suite_i, initHashes);
}
}
}
@ -9512,7 +9630,7 @@ ssl3_HandleClientHelloPart2(sslSocket *ss,
}
#endif
rv = ssl3_NegotiateCipherSuite(ss, suites);
rv = ssl3_NegotiateCipherSuite(ss, suites, PR_TRUE);
if (rv != SECSuccess) {
desc = handshake_failure;
errCode = SSL_ERROR_NO_CYPHER_OVERLAP;
@ -10231,7 +10349,6 @@ ssl3_SendDHServerKeyExchange(sslSocket *ss)
const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
SECStatus rv = SECFailure;
int length;
PRBool isTLS;
SECItem signed_hash = { siBuffer, NULL, 0 };
SSL3Hashes hashes;
SSLHashType hashAlg;
@ -10249,12 +10366,13 @@ ssl3_SendDHServerKeyExchange(sslSocket *ss)
return SECFailure;
}
rv = ssl_SelectDHEParams(ss, &groupDef, &params);
rv = ssl_SelectDHEGroup(ss, &groupDef);
if (rv == SECFailure) {
PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
return SECFailure;
}
params = ssl_GetDHEParams(groupDef);
rv = ssl_CreateDHEKeyPair(groupDef, params, &keyPair);
if (rv == SECFailure) {
ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
@ -10283,9 +10401,8 @@ ssl3_SendDHServerKeyExchange(sslSocket *ss)
goto loser;
}
isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
certPrivateKey = ss->sec.serverCert->serverKeyPair->privKey;
rv = ssl3_SignHashes(&hashes, certPrivateKey, &signed_hash, isTLS);
rv = ssl3_SignHashes(ss, &hashes, certPrivateKey, &signed_hash);
if (rv != SECSuccess) {
goto loser; /* ssl3_SignHashes has set err. */
}
@ -10351,7 +10468,6 @@ ssl3_SendServerKeyExchange(sslSocket *ss)
const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
SECStatus rv = SECFailure;
int length;
PRBool isTLS;
SECItem signed_hash = { siBuffer, NULL, 0 };
SSL3Hashes hashes;
SECKEYPublicKey *sdPub; /* public key for step-down */
@ -10390,9 +10506,9 @@ ssl3_SendServerKeyExchange(sslSocket *ss)
return rv;
}
isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
rv = ssl3_SignHashes(&hashes, ss->sec.serverCert->serverKeyPair->privKey,
&signed_hash, isTLS);
rv = ssl3_SignHashes(ss, &hashes,
ss->sec.serverCert->serverKeyPair->privKey,
&signed_hash);
if (rv != SECSuccess) {
goto loser; /* ssl3_SignHashes has set err. */
}
@ -10624,7 +10740,7 @@ ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
int errCode = SSL_ERROR_RX_MALFORMED_CERT_VERIFY;
SSL3AlertDescription desc = handshake_failure;
PRBool isTLS;
SignatureScheme sigScheme;
SignatureScheme sigScheme = ssl_sig_none;
SSLHashType hashAlg;
SSL3Hashes localHashes;
SSL3Hashes *hashesForVerify = NULL;
@ -10700,8 +10816,7 @@ ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
}
/* XXX verify that the key & kea match */
rv = ssl3_VerifySignedHashes(hashesForVerify, ss->sec.peerCert, &signed_hash,
isTLS, ss->pkcs11PinArg);
rv = ssl3_VerifySignedHashes(ss, sigScheme, hashesForVerify, &signed_hash);
if (rv != SECSuccess) {
errCode = PORT_GetError();
desc = isTLS ? decrypt_error : handshake_failure;
@ -11102,20 +11217,20 @@ ssl3_HandleClientKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ss->sec.keaKeyBits = EXPORT_RSA_KEY_LENGTH * BPB;
} else
skip:
if (kea_def->ephemeral) {
sslEphemeralKeyPair *keyPair;
/* There should be exactly one pair. */
PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
PORT_Assert(PR_PREV_LINK(&ss->ephemeralKeyPairs) ==
PR_NEXT_LINK(&ss->ephemeralKeyPairs));
keyPair = (sslEphemeralKeyPair *)PR_NEXT_LINK(&ss->ephemeralKeyPairs);
serverKeyPair = keyPair->keys;
ss->sec.keaKeyBits =
SECKEY_PublicKeyStrengthInBits(serverKeyPair->pubKey);
} else {
serverKeyPair = ss->sec.serverCert->serverKeyPair;
ss->sec.keaKeyBits = ss->sec.serverCert->serverKeyBits;
}
if (kea_def->ephemeral) {
sslEphemeralKeyPair *keyPair;
/* There should be exactly one pair. */
PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
PORT_Assert(PR_PREV_LINK(&ss->ephemeralKeyPairs) ==
PR_NEXT_LINK(&ss->ephemeralKeyPairs));
keyPair = (sslEphemeralKeyPair *)PR_NEXT_LINK(&ss->ephemeralKeyPairs);
serverKeyPair = keyPair->keys;
ss->sec.keaKeyBits =
SECKEY_PublicKeyStrengthInBits(serverKeyPair->pubKey);
} else {
serverKeyPair = ss->sec.serverCert->serverKeyPair;
ss->sec.keaKeyBits = ss->sec.serverCert->serverKeyBits;
}
if (!serverKeyPair) {
SSL3_SendAlert(ss, alert_fatal, handshake_failure);
@ -12555,7 +12670,6 @@ ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid)
sid->authKeyBits = ss->sec.authKeyBits;
sid->keaType = ss->sec.keaType;
sid->keaKeyBits = ss->sec.keaKeyBits;
sid->namedGroups = ss->namedGroups;
sid->lastAccessTime = sid->creationTime = ssl_Time();
sid->expirationTime = sid->creationTime + ssl3_sid_timeout;
sid->localCert = CERT_DupCertificate(ss->sec.localCert);
@ -12696,14 +12810,11 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
}
} else {
if (type == certificate_verify) {
computeHashes =
TLS13_IN_HS_STATE(ss, wait_cert_verify,
wait_0rtt_trial_decrypt);
computeHashes = TLS13_IN_HS_STATE(ss, wait_cert_verify);
} else if (type == finished) {
computeHashes =
TLS13_IN_HS_STATE(ss, wait_cert_request, wait_finished,
wait_0rtt_finished,
wait_0rtt_trial_decrypt);
wait_0rtt_finished);
}
}
@ -12734,8 +12845,9 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
hdr[2] = (PRUint8)(length >> 8);
hdr[3] = (PRUint8)(length);
/* Start new handshake hashes when we start a new handshake */
if (ss->ssl3.hs.msg_type == client_hello) {
/* Start new handshake hashes when we start a new handshake. Unless this is
* TLS 1.3 and we sent a HelloRetryRequest. */
if (ss->ssl3.hs.msg_type == client_hello && !ss->ssl3.hs.helloRetry) {
rv = ssl3_RestartHandshakeHashes(ss);
if (rv != SECSuccess) {
return rv;
@ -13553,11 +13665,13 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
isTLS = (PRBool)(crSpec->version > SSL_LIBRARY_VERSION_3_0);
if (IS_DTLS(ss)) {
if (!dtls_IsRelevant(ss, crSpec, cText, &seq_num)) {
PRBool sameEpoch;
if (!dtls_IsRelevant(ss, cText, &sameEpoch, &seq_num)) {
ssl_ReleaseSpecReadLock(ss); /*****************************/
databuf->len = 0; /* Needed to ensure data not left around */
/* Drop the packet, but first see if retransmission is needed. */
return dtls_MaybeRetransmitHandshake(ss, cText);
/* Maybe retransmit if needed. */
return dtls_MaybeRetransmitHandshake(ss, cText, sameEpoch);
}
} else {
seq_num = crSpec->read_seq_num + 1;
@ -13593,6 +13707,19 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
}
}
/* We're waiting for another ClientHello, which will appear unencrypted.
* Use the content type to tell whether this is should be discarded.
*
* XXX If we decide to remove the content type from encrypted records, this
* will become much more difficult to manage. */
if (ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_hrr &&
cText->type == content_application_data) {
ssl_ReleaseSpecReadLock(ss); /*****************************/
PORT_Assert(ss->ssl3.hs.ws == wait_client_hello);
databuf->len = 0;
return SECSuccess;
}
/* IMPORTANT: Unprotect functions MUST NOT send alerts
* because we still hold the spec read lock. Instead, if they
* return SECFailure, they set *alert to the alert to be sent. */
@ -13609,7 +13736,9 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
SSL_DBG(("%d: SSL3[%d]: decryption failed", SSL_GETPID(), ss->fd));
if (IS_DTLS(ss) || TLS13_IN_HS_STATE(ss, wait_0rtt_trial_decrypt)) {
if (IS_DTLS(ss) ||
(ss->sec.isServer &&
ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_trial)) {
/* Silently drop the packet */
databuf->len = 0; /* Needed to ensure data not left around */
return SECSuccess;
@ -13714,7 +13843,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
return SECSuccess;
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 &&
ss->sec.isServer &&
TLS13_IN_HS_STATE(ss, wait_0rtt_end_of_early_data)) {
ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) {
return tls13_HandleEarlyApplicationData(ss, databuf);
}
(void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
@ -13835,12 +13964,12 @@ ssl3_InitState(sslSocket *ss)
ssl3_InitCipherSpec(ss->ssl3.crSpec);
ssl3_InitCipherSpec(ss->ssl3.prSpec);
ss->ssl3.crSpec->version = ss->ssl3.prSpec->version = ss->vrange.max;
ssl_ReleaseSpecWriteLock(ss);
ss->ssl3.hs.sendingSCSV = PR_FALSE;
ss->ssl3.hs.preliminaryInfo = 0;
ss->ssl3.hs.peerSupportsFfdheGroups = PR_FALSE;
ss->ssl3.hs.ws = (ss->sec.isServer) ? wait_client_hello : wait_server_hello;
ssl_ReleaseSpecWriteLock(ss);
PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData));
@ -13873,6 +14002,8 @@ ssl3_InitState(sslSocket *ss)
PORT_Memset(&ss->ssl3.hs.newSessionTicket, 0,
sizeof(ss->ssl3.hs.newSessionTicket));
ss->ssl3.hs.zeroRttState = ssl_0rtt_none;
ssl_DisableNonSuiteBGroups(ss);
ss->ssl3.initialized = PR_TRUE;
@ -14143,8 +14274,11 @@ ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache)
ssl_GetXmitBufLock(ss); /**************************************/
/* start off a new handshake. */
rv = (ss->sec.isServer) ? ssl3_SendHelloRequest(ss)
: ssl3_SendClientHello(ss, PR_FALSE);
if (ss->sec.isServer) {
rv = ssl3_SendHelloRequest(ss);
} else {
rv = ssl3_SendClientHello(ss, client_hello_renegotiation);
}
ssl_ReleaseXmitBufLock(ss); /**************************************/
return rv;
@ -14243,7 +14377,7 @@ ssl3_DestroySSL3Info(sslSocket *ss)
if (ss->ssl3.hs.trafficSecret)
PK11_FreeSymKey(ss->ssl3.hs.trafficSecret);
ss->ssl3.hs.doing0Rtt = PR_FALSE;
ss->ssl3.hs.zeroRttState = ssl_0rtt_none;
/* Destroy TLS 1.3 buffered early data. */
tls13_DestroyEarlyData(&ss->ssl3.hs.bufferedEarlyData);

Просмотреть файл

@ -129,7 +129,7 @@ ssl_ECPubKey2NamedGroup(const SECKEYPublicKey *pubKey)
!(policyFlags & NSS_USE_ALG_IN_SSL_KX)) {
return NULL;
}
for (i = 0; i < ssl_named_group_count; ++i) {
for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
if (ssl_named_groups[i].oidTag == oidData->offset) {
return &ssl_named_groups[i];
}
@ -424,17 +424,23 @@ tls13_ImportECDHKeyShare(sslSocket *ss, SECKEYPublicKey *peerKey,
}
const namedGroupDef *
ssl_GetECGroupWithStrength(PRUint32 curvemsk, unsigned int requiredECCbits)
ssl_GetECGroupWithStrength(sslSocket *ss, unsigned int requiredECCbits)
{
int i;
for (i = 0; i < ssl_named_group_count; i++) {
if (ssl_named_groups[i].type != group_type_ec ||
ssl_named_groups[i].bits < requiredECCbits) {
for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
const namedGroupDef *group;
if (ss) {
group = ss->namedGroupPreferences[i];
} else {
group = &ssl_named_groups[i];
}
if (!group || group->type != group_type_ec ||
group->bits < requiredECCbits) {
continue;
}
if ((curvemsk & (1U << i))) {
return &ssl_named_groups[i];
if (!ss || ssl_NamedGroupEnabled(ss, group)) {
return group;
}
}
PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
@ -486,7 +492,7 @@ ssl_GetECGroupForServerSocket(sslSocket *ss)
requiredECCbits = certKeySize;
}
return ssl_GetECGroupWithStrength(ss->namedGroups, requiredECCbits);
return ssl_GetECGroupWithStrength(ss, requiredECCbits);
}
/* function to clear out the lists */
@ -508,7 +514,7 @@ static PRStatus
ssl_ECRegister(void)
{
SECStatus rv;
PORT_Assert(PR_ARRAY_SIZE(gECDHEKeyPairs) == ssl_named_group_count);
PORT_Assert(PR_ARRAY_SIZE(gECDHEKeyPairs) == SSL_NAMED_GROUP_COUNT);
rv = NSS_RegisterShutdown(ssl_ShutdownECDHECurves, gECDHEKeyPairs);
if (rv != SECSuccess) {
gECDHEInitError = PORT_GetError();
@ -624,6 +630,7 @@ ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
SSL3Hashes hashes;
SECItem signature = { siBuffer, NULL, 0 };
SSLHashType hashAlg;
SignatureScheme sigScheme;
SECItem ec_params = { siBuffer, NULL, 0 };
SECItem ec_point = { siBuffer, NULL, 0 };
@ -672,7 +679,6 @@ ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
PORT_Assert(ss->ssl3.prSpec->version <= SSL_LIBRARY_VERSION_TLS_1_2);
if (ss->ssl3.prSpec->version == SSL_LIBRARY_VERSION_TLS_1_2) {
SignatureScheme sigScheme;
rv = ssl_ConsumeSignatureScheme(ss, &b, &length, &sigScheme);
if (rv != SECSuccess) {
goto loser; /* malformed or unsupported. */
@ -686,6 +692,7 @@ ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
} else {
/* Use ssl_hash_none to represent the MD5+SHA1 combo. */
hashAlg = ssl_hash_none;
sigScheme = ssl_sig_none;
}
rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
@ -720,8 +727,7 @@ ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
goto alert_loser;
}
rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
isTLS, ss->pkcs11PinArg);
rv = ssl3_VerifySignedHashes(ss, sigScheme, &hashes, &signature);
if (rv != SECSuccess) {
errCode =
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
@ -780,7 +786,7 @@ ssl3_SendECDHServerKeyExchange(sslSocket *ss)
{
SECStatus rv = SECFailure;
int length;
PRBool isTLS, isTLS12;
PRBool isTLS12;
SECItem signed_hash = { siBuffer, NULL, 0 };
SSLHashType hashAlg = ssl_hash_none;
SSL3Hashes hashes;
@ -843,11 +849,10 @@ ssl3_SendECDHServerKeyExchange(sslSocket *ss)
goto loser;
}
isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
rv = ssl3_SignHashes(&hashes, ss->sec.serverCert->serverKeyPair->privKey,
&signed_hash, isTLS);
rv = ssl3_SignHashes(ss, &hashes,
ss->sec.serverCert->serverKeyPair->privKey, &signed_hash);
if (rv != SECSuccess) {
goto loser; /* ssl3_SignHashes has set err. */
}
@ -1015,11 +1020,11 @@ ssl_DisableNonSuiteBGroups(sslSocket *ss)
return;
}
for (i = 0; i < ssl_named_group_count; ++i) {
PORT_Assert(ssl_named_groups[i].index == i);
if (ssl_named_groups[i].type == group_type_ec &&
!ssl_named_groups[i].suiteb) {
ss->namedGroups &= ~(1U << ssl_named_groups[i].index);
for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
if (ss->namedGroupPreferences[i] &&
ss->namedGroupPreferences[i]->type == group_type_ec &&
!ss->namedGroupPreferences[i]->suiteb) {
ss->namedGroupPreferences[i] = NULL;
}
}
}
@ -1049,24 +1054,26 @@ ssl_SendSupportedGroupsXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
return 0;
}
PORT_Assert(sizeof(enabledGroups) > ssl_named_group_count * 2);
for (i = 0; i < ssl_named_group_count; ++i) {
if (ssl_named_groups[i].type == group_type_ec && !ec) {
PORT_Assert(sizeof(enabledGroups) > SSL_NAMED_GROUP_COUNT * 2);
for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
const namedGroupDef *group = ss->namedGroupPreferences[i];
if (!group) {
continue;
}
if (ssl_named_groups[i].type == group_type_ff && !ff) {
if (group->type == group_type_ec && !ec) {
continue;
}
if (!ssl_NamedGroupEnabled(ss, &ssl_named_groups[i])) {
if (group->type == group_type_ff && !ff) {
continue;
}
if (!ssl_NamedGroupEnabled(ss, group)) {
continue;
}
if (append) {
enabledGroups[enabledGroupsLen++] = ssl_named_groups[i].name >> 8;
enabledGroups[enabledGroupsLen++] = ssl_named_groups[i].name & 0xff;
} else {
enabledGroupsLen += 2;
(void)ssl_EncodeUintX(group->name, 2, &enabledGroups[enabledGroupsLen]);
}
enabledGroupsLen += 2;
}
extension_length =
@ -1168,7 +1175,9 @@ static SECStatus
ssl_UpdateSupportedGroups(sslSocket *ss, SECItem *data)
{
PRInt32 list_len;
PRUint32 peerGroups = 0;
unsigned int i;
const namedGroupDef *enabled[SSL_NAMED_GROUP_COUNT] = { 0 };
PORT_Assert(SSL_NAMED_GROUP_COUNT == PR_ARRAY_SIZE(enabled));
if (!data->data || data->len < 4) {
(void)ssl3_DecodeError(ss);
@ -1182,7 +1191,13 @@ ssl_UpdateSupportedGroups(sslSocket *ss, SECItem *data)
return SECFailure;
}
/* build bit vector of peer's supported groups */
/* disable all groups and remember the enabled groups */
for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
enabled[i] = ss->namedGroupPreferences[i];
ss->namedGroupPreferences[i] = NULL;
}
/* Read groups from data and enable if in |enabled| */
while (data->len) {
const namedGroupDef *group;
PRInt32 curve_name =
@ -1192,7 +1207,12 @@ ssl_UpdateSupportedGroups(sslSocket *ss, SECItem *data)
}
group = ssl_LookupNamedGroup(curve_name);
if (group) {
peerGroups |= (1U << group->index);
for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
if (enabled[i] && group == enabled[i]) {
ss->namedGroupPreferences[i] = enabled[i];
break;
}
}
}
/* "Codepoints in the NamedCurve registry with a high byte of 0x01 (that
@ -1203,21 +1223,19 @@ ssl_UpdateSupportedGroups(sslSocket *ss, SECItem *data)
ss->ssl3.hs.peerSupportsFfdheGroups = PR_TRUE;
}
}
/* Note: if ss->opt.requireDHENamedGroups is set, we disable DHE cipher
* suites, but we do that in ssl3_config_match(). */
if (!ss->opt.requireDHENamedGroups && !ss->ssl3.hs.peerSupportsFfdheGroups) {
/* If we don't require that DHE use named groups, and no FFDHE was
* included, we pretend that they support all the FFDHE groups we do. */
unsigned int i;
for (i = 0; i < ssl_named_group_count; ++i) {
if (ssl_named_groups[i].type == group_type_ff) {
peerGroups |= (1U << ssl_named_groups[i].index);
for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
if (enabled[i] && enabled[i]->type == group_type_ff) {
ss->namedGroupPreferences[i] = enabled[i];
}
}
}
/* What curves do we support in common? */
ss->namedGroups &= peerGroups;
return SECSuccess;
}

Просмотреть файл

@ -2131,6 +2131,9 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data)
}
}
if (parsed_session_ticket->srvName.data != NULL) {
if (sid->u.ssl3.srvName.data) {
SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE);
}
sid->u.ssl3.srvName = parsed_session_ticket->srvName;
}
if (parsed_session_ticket->alpnSelection.data != NULL) {
@ -3300,15 +3303,16 @@ tls13_HandleKeyShareEntry(sslSocket *ss, SECItem *data)
goto loser;
}
groupDef = ssl_LookupNamedGroup(group);
rv = ssl3_ConsumeHandshakeVariable(ss, &share, 2, &data->data,
&data->len);
if (rv != SECSuccess) {
goto loser;
}
/* If the group is disabled, continue. */
if (!groupDef) {
return SECSuccess;
}
rv = ssl3_ConsumeHandshakeVariable(ss, &share, 2, &data->data,
&data->len);
if (rv != SECSuccess)
goto loser;
ks = PORT_ZNew(TLS13KeyShareEntry);
if (!ks)
goto loser;
@ -3724,7 +3728,7 @@ tls13_ClientSendEarlyDataXtn(sslSocket *ss,
return -1;
}
ss->ssl3.hs.doing0Rtt = PR_TRUE;
ss->ssl3.hs.zeroRttState = ssl_0rtt_sent;
ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
ssl_tls13_early_data_xtn;
@ -3758,11 +3762,18 @@ tls13_ServerHandleEarlyDataXtn(sslSocket *ss, PRUint16 ex_type,
return SECFailure;
}
/* Keep track of negotiated extensions.
* IMPORTANT: Record the presence of the extension only. This is
* only one of several things that the 0-RTT processing code uses
* in determining whether to accept 0-RTT.
*/
if (IS_DTLS(ss)) {
/* Save the null spec, which we should be currently reading. We will
* use this when 0-RTT sending is over. */
ssl_GetSpecReadLock(ss);
ss->ssl3.hs.nullSpec = ss->ssl3.crSpec;
tls13_CipherSpecAddRef(ss->ssl3.hs.nullSpec);
PORT_Assert(ss->ssl3.hs.nullSpec->cipher_def->cipher == cipher_null);
ssl_ReleaseSpecReadLock(ss);
}
ss->ssl3.hs.zeroRttState = ssl_0rtt_sent;
ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
return SECSuccess;
@ -3777,6 +3788,7 @@ tls13_ServerSendEarlyDataXtn(sslSocket *ss,
SSL_TRC(3, ("%d: TLS13[%d]: send early_data extension",
SSL_GETPID(), ss->fd));
PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted);
if (maxBytes < 4) {
PORT_Assert(0);
return 0;
@ -3818,6 +3830,7 @@ tls13_ClientHandleEarlyDataXtn(sslSocket *ss, PRUint16 ex_type,
/* Keep track of negotiated extensions. */
ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
ss->ssl3.hs.zeroRttState = ssl_0rtt_accepted;
return SECSuccess;
}

Просмотреть файл

@ -205,7 +205,7 @@ ssl_BeginClientHandshake(sslSocket *ss)
ssl_GetSSL3HandshakeLock(ss);
ssl_GetXmitBufLock(ss);
rv = ssl3_SendClientHello(ss, PR_FALSE);
rv = ssl3_SendClientHello(ss, client_hello_initial);
ssl_ReleaseXmitBufLock(ss);
ssl_ReleaseSSL3HandshakeLock(ss);

Просмотреть файл

@ -237,6 +237,9 @@ typedef enum {
SSL_ERROR_RX_UNEXPECTED_EXTENSION = (SSL_ERROR_BASE + 151),
SSL_ERROR_MISSING_SUPPORTED_GROUPS_EXTENSION = (SSL_ERROR_BASE + 152),
SSL_ERROR_TOO_MANY_RECORDS = (SSL_ERROR_BASE + 153),
SSL_ERROR_RX_UNEXPECTED_HELLO_RETRY_REQUEST = (SSL_ERROR_BASE + 154),
SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST = (SSL_ERROR_BASE + 155),
SSL_ERROR_BAD_2ND_CLIENT_HELLO = (SSL_ERROR_BASE + 156),
SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
} SSLErrorCodes;
#endif /* NO_SECURITY_ERROR_ENUM */

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше