[openssl-commits] [tools] master update

Rich Salz rsalz at openssl.org
Sat Feb 3 23:24:09 UTC 2018


The branch master has been updated
       via  27296557068a17464f17533d89d4fa6f3555b909 (commit)
      from  bb40e3e6bcd68b3ba9ba4e71751d9f8e630f63cf (commit)


- Log -----------------------------------------------------------------
commit 27296557068a17464f17533d89d4fa6f3555b909
Author: Rich Salz <rsalz at akamai.com>
Date:   Sat Feb 3 18:23:50 2018 -0500

    Add our release tools

-----------------------------------------------------------------------

Summary of changes:
 release-tools/MKRELEASE.md       | 168 +++++++++++++++
 release-tools/README.md          | 320 +++++++++++++++++++++++++++++
 release-tools/do-copyright-year  |  40 ++++
 release-tools/do-release.pl      | 209 +++++++++++++++++++
 release-tools/mkrelease.pl       | 427 +++++++++++++++++++++++++++++++++++++++
 release-tools/release-check.pl   | 215 ++++++++++++++++++++
 release-tools/release-date.pl    |  64 ++++++
 release-tools/release-git.pl     | 164 +++++++++++++++
 release-tools/release-update.pl  | 153 ++++++++++++++
 release-tools/release-version.pl | 179 ++++++++++++++++
 10 files changed, 1939 insertions(+)
 create mode 100644 release-tools/MKRELEASE.md
 create mode 100644 release-tools/README.md
 create mode 100755 release-tools/do-copyright-year
 create mode 100644 release-tools/do-release.pl
 create mode 100644 release-tools/mkrelease.pl
 create mode 100644 release-tools/release-check.pl
 create mode 100644 release-tools/release-date.pl
 create mode 100644 release-tools/release-git.pl
 create mode 100644 release-tools/release-update.pl
 create mode 100644 release-tools/release-version.pl

diff --git a/release-tools/MKRELEASE.md b/release-tools/MKRELEASE.md
new file mode 100644
index 0000000..04d6dc7
--- /dev/null
+++ b/release-tools/MKRELEASE.md
@@ -0,0 +1,168 @@
+# Documentation on the mkrelease.pl script
+
+This file provides an overview of the mkrelease.pl script, and how to
+configure some of its parameters (by setting environment variables).
+It is normally run by following the process in README.md and should be
+run in a pristine directgory of the branch to be released, which must
+be a stable branch.
+
+The script handles most of the processes involved in making a release
+including:
+
+1. Doing `make update`
+2. Changing version numbers in various files
+3. Tagging release
+4. Making the tarballs, .md5, .sha1, .sha256 and .gpg files
+5. Creating the signed email announcement, including hashes of release
+6. Uploading files to dev.openssl.org
+7. Updating the version for next release
+
+If you plan to make an actual release make sure your GPG key is included
+in the [OMC list](https://www.openssl.org/community/omc.html) on the website
+and in the file doc/fingerprints.txt of *all* active branches.
+
+The script mkrelease.pl calls the files release-check.pl, release-date.pl,
+release-git.pl, release-update.pl and release-version.pl, which are expected
+to all be in the same directory.
+
+You are advised to clone a fresh repository. Unless you specify `--no-clean`
+the release process will run `git clean -x -d -f`
+*WARNING* this will delete ALL untracked files from the current branch.
+
+From the branch directory if you run:
+
+        perl /path/to/mkrelease.pl --reviewer=name
+
+It should perform all of the above steps and commit changes locally. You can
+then sanity check these with `git log` before pushing them to the public repo.
+
+## Environment Variables
+
+- OPENSSL<br>
+  Path to openssl utility to use. Default is `openssl`.
+
+- OPENSSL_TAR<br>
+  The tar command to use when creating the tarball. Default is `tar`.
+
+- OPENSSL_GPG<br>
+  The gpg command to use when signing a tarball or announcement.
+  The default is `gpg` which will use gpg with the default key.
+  If you wish to use a different, key set OPENSSL_GPG to include
+  appropriate options.
+
+- OPENSSL_GPG_TAR<br>
+  Command to use to sign a tarball.
+  The default is: `$OPENSSL_GPG --use-agent -sba`
+
+- OPENSSL_GPG_ANNOUNCE<br>
+  The command to use to sign a tarball.
+  The default is: `$OPENSSL_GPG --use-agent -sta --clearsign`
+
+- OPENSSL_SCP<br>
+  The command to use to upload files.
+  The default is `scp`
+
+- OPENSSL_SCP_HOST<br>
+  The host (and optional username) needed to upload files.
+  The default is `dev.openssl.org`, but you might want to change this to
+  `username at dev.openssl.org`
+
+- OPENSSL_SCP_DIR<br>
+  The directory to upload files to.
+  Normally this wont be changed from the default which is
+  `$OPENSSL_SCP_HOST:~openssl/dist/new`
+  This is a holding area on dev.openssl.org where distributions are uploaded
+  temporarily before being moved to the web and ftp directories.
+
+For local testing, you can do something like this:
+
+        export OPENSSL_SCP=cp
+        export OPENSSL_SCP_DIR="$HOME/testdir"
+
+## Options
+
+- `--revert`<br>
+  Remove all local changes from repository and delete any release tag. This
+  returns the local tree to the same state as before a release attempt was
+  made.
+
+- `--reviewer=name`<br>
+  Add reviewer `name` to list of reviewers in commit message. Any valid
+  name for checking OMC membership will work.
+  This option may be used multiple times; at least one is required.
+
+- `--enter-pre`<br>
+  Instead of making a full release enter pre-release state. This by itself
+  will not produce a release it will just change version numbers and commit
+  the changes. Subsequent releases on this branch will be pre-release
+  versions. This option should NOT be used if the branch is already in
+  pre-release state.
+
+- `--leave-pre`<br>
+  For a branch in pre-release state, leave pre-release and make a full release.
+
+- `--label=label`<br>
+   Add the textual label `label` to the version string, where `label` must be
+   one of `alpha` or `beta`. While in pre-release state a label *must* be
+   provided.
+
+- `--no-upload`<br>
+  Do not attempt to upload release files to dev.openssl.org
+
+- `--no-clean`<br>
+  Do not clean untracked files from directory. Warning: if you use this option
+  you can end up with extraneous files in the distribution tarball.
+
+- `--no-update`<br>
+  Do not perform a `make update`.
+
+- `--verbose`<br>
+  Be more verbose at what is going on
+
+- `--debug`<br>
+  Include debug output to describe all actions in detail
+
+- `--git-info`<br>
+  Just print out details of all git branch information and exit
+
+- `--git-branch-info`<br>
+  Print out details of the currently detected branch and exit
+
+- `--branch-version=version`<br>
+  Use branch `version` instead of the one autodetected for the current branch.
+  This option is not normally needed.
+
+# The do-release script
+
+The do-release.pl script copies distributions from the temporary holding area
+to the http and ftp areas. It it intended to be run as the `openssl` user on
+dev.openssl.org.
+
+It does the following:
+
+1. Copy OpenSSL release files from the holding area to the http and ftp
+   locations: currently /v/openssl/www/source and /v/openssl/ftp/source
+2. Move OpenSSL release files from holding area to ~openssl/dist/old By
+   doing this the script wont try and make a release again with old files.
+3. Mail the release message. This is sent to openssl-dev openssl-users and
+   openssl-announce (it needs to be approved in openssl-announce). The
+   subject line is `OpenSSL version xxx released`.
+
+## do-release options
+
+- `--copy`<br>
+  Copy files to http and ftp directories.  **You will have to manually move
+  the OLD files to old/<SUBDIR> directories.**
+
+- `--move`<br>
+  Move files from holding area to ~openssl/dist/old
+
+- `--mail`<br>
+  Send out announcement email: if this option is not given, the command you
+  need to call to send the release mail will be printed out.
+
+- `--full-release`<br>
+  Perform all operations for a release (copy, move and mail).
+
+Note: because several of these options are irreversible they have to be
+explicitly included.
diff --git a/release-tools/README.md b/release-tools/README.md
new file mode 100644
index 0000000..7b3767e
--- /dev/null
+++ b/release-tools/README.md
@@ -0,0 +1,320 @@
+# HOW TO MAKE A RELEASE
+
+This file documents how to make an OpenSSL release.  Please fix any
+errors you find while doing, or just after, your next release!
+
+Releases are done by one person, with a second person acting as the
+reviewer and additional tester.
+
+## Pre-requisites
+
+Have a local clone of the website repo:
+
+        openssl-git at git.openssl.org:openssl-web.git
+
+Make sure you can sudo to the openssl user on dev.openssl.org; this is
+usually done by being in the openssl group.  For example, ssh to the
+server and run this command:
+
+        sudo -u openssl id
+
+## Setup
+
+The day before the release, freeze the main repository.  This locks out
+everyone but the named user, who is doing the release, from doing any pushes.
+Someone other than the person doing the release should run the command.
+For example:
+
+        ssh openssl-git at git.openssl.org freeze openssl NAME
+
+## Making the tarball and announcements
+
+This section generates the tarball and announcements locally.  It makes
+no changes which cannot be easily undone.  You will have to repeat this
+section for each version being released, so it is often easier to have
+separate copies:
+
+        git clone openssl-git at git.openssl.org:openssl.git rel-102
+        cd rel-102
+        git branch --track OpenSSL_1_0_2-stable origin/OpenSSL_1_0_2-stable
+        git checkout OpenSSL_1_0_2-stable
+
+Make sure that the CHANGES and NEWS files have been updated and reviewed.
+NEWS should contain a summary of any changes for the release, and for a
+security release is (often just a list of the CVEs addressed. You should also
+update NEWS in the master branch to include details of all releases. Just
+update the NEWS bullet points - do not change the release date, keep it as
+**under development**.
+
+Add any security fixes to the tree. Commit them but *do not push*.
+
+Make sure that the copyrights are updated.  This script will update
+the copyright markers and commit the changes (where $HERE stands for
+the directory where this README is):
+
+        $HERE/do-copyright-year
+
+Perform the local automated release steps. This can normally be done with:
+
+        perl $HERE/mkrelease.pl --reviewer=NAME
+
+Alternatively, to use the openssl-team PGP key:
+
+        export OPENSSL_GPG_KEYID=8B3D79F5
+        perl $HERE/mkrelease.pl --reviewer=NAME
+
+See $HERE/MKRELEASE.md for details of the options to mkrelease.pl.
+This will leave a handful of files in the parent directory of where
+you extracted the release.
+See below for details of how to do perform this step manually if you want
+to or have to.
+
+Verify that the results of the script are sensible. Check
+the commits the automated release process has performed, using for example
+`git log`. Check the signed announcement RELEASE.asc file. Maybe check
+that the tarball length and hashes match in the .md5, .sha1, and review
+the announcment file. *Do not push* changes to the public repo at this stage.
+
+Both the person doing the release and the reviewer should sanity-check the
+release at this point. Checks to consider include the following:
+
+- Builds and make test passes on multiple plaforms - Linux, Windows, etc.
+- Builds from tarball
+
+Send the auto-generated commits to the reviewer and await their +1.
+Repeat from the begining of this section if you need to release
+multiple versions.
+
+## Website updates
+
+The changes in this section should be made in your copy of the web repo.
+
+Update the news/newsflash.txt file. This normally is one or two lines. Just
+copy and paste existing announcements making minor changes for the date and
+version number as necessary.
+
+Update the news/vulnerabilities.xml file if appropriate.
+
+If there is a Security Advisory then copy it into the news/secadv directory.
+
+Commit your changes, but *do not push* them to the website.
+
+## Publishing the release
+
+*BE CAREFUL*  This section makes everything visible and is therefore
+largely irreversible. If you are performing a dry run then DO NOT
+perform any steps in this section.
+
+Check that release has been uploaded properly. The release tarballs and
+associated files should be in ~openssl/dist/new.  They should be owned by the
+openssl userid and world-readable.
+
+Copy the tarballs to appropriate directories. This can be
+done using the do-release.pl script.  See MKRELEASE.md for a description of
+the options. For example:
+
+        sudo -u openssl perl ~openssl/do-release.pl --copy --move
+
+This will copy the relevant files to the website and move them from
+~openssl/dist/new to ~openssl/dist/old so they will not seen by a subsequent
+release. Alternatively if you want to perform one release at a time or copy/move
+the files manually, see below.
+
+The do-release.pl script will display the commands you will need to issue to
+send the announcement emails later. Keep a note of those commands for future
+reference.
+
+Verify that the tarballs are available via FTP:
+
+        ftp://ftp.openssl.org/source/
+
+And that they are ready for the website:
+
+        ls /var/www/openssl/source
+
+Push your local changes made above to the public repo. You will
+typically want to sanity check this with:
+
+        git push -n
+
+Push new tags to public repo. Again sanity check with:
+
+        git push --tags -n
+
+to make sure no local tags were pushed.
+
+##  Updating the website
+
+Push the website changes you made earlier to the OpenSSL website repo.  When
+you do this, the website will get updated and a script to flush the Akamai CDN
+cache will be run.  You can look at things on www-origin.openssl.org; the
+CDN-hosted www.openssl.org should only be a few minutes delayed.
+
+Verify that the release notes, which are built from the CHANGES file in the
+release, have been updated. This is done automatically by the commit-hook, but
+if you see a problem, try the following steps:
+
+        cd /var/www/openssl
+        sudo -u openssl -H make relupd
+        sudo -u openssl ./bin/purge-one-hour
+
+Wait for a while for the Akamai flush to work (normally within a few minutes).
+Have a look at the website and news announcement at:
+
+        https://www.openssl.org/
+        https://www.openssl.org/news/
+
+Check the download page has updated properly:
+
+        https://www.openssl.org/source/
+
+Check the notes look sensible at:
+
+        https://www.openssl.org/news/news.html
+
+Also check the notes here:
+
+        https://www.openssl.org/news/openssl-1.0.2-notes.html
+        https://www.openssl.org/news/openssl-1.1.0-notes.html
+
+## Send the announcement mail
+
+Send out the announcements. Generic release announcement messages will be
+created automatically by the build script and the commands you need to use to
+send them were displayed when you executed do-release.pl above.
+These should normally be sent from the openssl account. These are sent to
+openssl-users, openssl-project, and openssl-announce.
+
+If do-release.pl was used with `--move` be sure to move the
+announcement text files away from the staging directory after they have been
+sent.  This is done as follows (with VERSION replaced with the version of
+OpenSSL to announce):
+
+        sudo -u openssl \
+            mv ~openssl/dist/new/openssl-VERSION.txt.asc ~openssl/dist/old
+
+Send out the Security Advisory if there is one. Copy the file to the
+openssl user home directory, and then do the following
+
+        sudo -u openssl gpg -u 8B3D79F5 --clearsign secadv_FILENAME
+        sudo -u openssl mutt -s "OpenSSL Security Advisory" \
+                openssl-project openssl-users openssl-announce
+                <~openssl/secadv_FILENAME.txt.asc
+
+Approve the openssl-announce email.  Go to
+<https://mta.openssl.org/mailman/admindb/openssl-announce>
+and approve the messages.
+The administration password needed for approval is held in /opt/mailman/README
+on mta.openssl.org
+
+Check the mailing list messages have arrived.
+
+## Finish
+
+Unfreeze the repository.
+
+        ssh openssl-git at git.openssl.org unfreeze openssl
+
+If this release includes security fixes with a CVE then you should inform
+MITRE about them. See the instructions at the top of cvepool.txt in bureau.
+
+Check mailing lists over the next few hours for reports of any success
+or failure. If necessary fix these and in the worst case make another
+release.
+
+# MANUAL PROCESS
+
+If for some reason you cannot use, or do not trust, release script
+mkrelease.pl then you can perform the release manually.  This is difficult to
+get right so you should avoid it if possible.
+
+Check what the automated release did for previous releases. This is the best
+way to get a feel for what happens. You can do this by checking the commit
+logs before a release tag for example:
+
+        git log --reverse 0d7717f..ebe2219
+
+The first two commits are security fixes. The third commit is (as the log
+message implies) an update of the NEWS file. The next commit which has the
+automated log message "Prepare for 1.0.1g release" includes the steps
+necessary to make the release.
+
+## Manually building the release files
+
+Do a `make update`. If necessary commit. You can push this commit to
+the repo so you have as few local changes as possible. Note that even if
+"make update" does not make any visible changes it can still update timestamps
+on some files which avoid some problems with builds (e.g. if the source files
+are all made read only).
+
+Update NEWS, README and CHANGES. These should contain the date and
+the correct version in the appropriate format.
+
+Update crypto/opensslv.h which contains the version. This contains the
+version number in the appropriate formats. For OPENSSL_VERSION_NUMBER and
+normal (not pre) releases you change the last digit from 0 (meaning -dev)
+to f (meaning release). Change the text forms in OPENSSL_VERSION_TEXT for
+normal and FIPS builds.
+
+Double-check that the version is right. If you mess up the syntax you can end
+up with the wrong release number or worse break compilation.
+
+Commit the changes you made so far, and check that the logs look sensible.
+
+Make a local tag; the public repo requires annotated tags:
+
+        git tag -s -m "OpenSSL 1.0.2L release tag" OpenSSL_1_0_2L
+
+or if you want to use the openssl-team key:
+
+        git tag -u 8B3D79F5 -m "OpenSSL 1.0.2L release tag" OpenSSL_1_0_2L
+
+Make the release tarball. You do this with:
+
+        make dist
+
+Create .sha1, .sha256 and .asc files manually. You can use:
+
+        openssl sha1
+        openssl sha256
+
+Create .sha1, .sha256 and .asc files manually. You can use the openssl sha1 and
+sha256 commands, obviously. Sign the tarball:
+
+        gpg -sba opensslversion.tar.gz
+
+or if you want to use the openssl-team key:
+
+        gpg -u 8B3D79F5 -sba opensslversion.tar.gz
+
+Create an announcement file. You can use an existing one as a
+template for example something in ~openssl/dist/old/ update the version
+numbers, tarball size and hashes. Sign announcement with:
+
+        gpg -sta --clearsign announce.txt
+
+or if you want to use the openssl-team key:
+
+        gpg -u 8B3D79F5 -sta --clearsign announce.txt
+
+Prepare for next development version by updating CHANGES, NEWS, README
+crypto/opensslv.h and openssl.spec. The automated scripts use the comment
+message `Prepare for 1.0.1h-dev`.
+
+Be absolutely *certain* you did not make any mistakes, so check
+several times preferably by different people.
+
+Upload tarballs to dev.openssl.org
+
+## Manually releasing the files
+
+If you do not want to use do-release.pl, you can manually perform
+the steps necessary for the release. This is (fortunately) much simpler
+than the manual release process above.
+
+Copy release files to web source directory. The four files (tarball,
+sha1, .sha256 and .asc) need to be manually copied to /var/www/openssl/source
+Also move any outdated releases to /var/www/openssl/source/old/SUBDIR
+
+Copy files to ftp source directory, /srv/ftp/source.
+Also move any oudated releases to /srv/ftp/source/old/SUBDIR
diff --git a/release-tools/do-copyright-year b/release-tools/do-copyright-year
new file mode 100755
index 0000000..59b9235
--- /dev/null
+++ b/release-tools/do-copyright-year
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+#
+# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+this_year=`date +%Y`
+some_year="[12][0-9][0-9][0-9]"
+year_range="(${some_year})(-${some_year})?"
+
+copyright_owner="The OpenSSL Project"
+copyright="Copyright .*${year_range} .*${copyright_owner}"
+
+# sed_script:
+#   for all lines that contain ${copyright} : {
+#     replace years yyyy-zzzz (or year yyyy) by yyyy-${this_year}
+#     replace repeated years yyyy-yyyy by yyyy
+#   }
+ss=/tmp/sed$$
+cat <<EOF >$ss
+/${copyright}/ {
+s|${year_range}|\1-${this_year}|
+s|(${some_year})-\1|\1|
+}
+EOF
+
+NYD=`date +%Y-01-01`
+echo Updating copryight
+git diff-tree -r --name-only `git rev-list -1 --before=$NYD HEAD`..HEAD \
+	| while read FILE ; do
+    sed -E -f /tmp/sed$$ "$FILE" >/tmp/$$
+    mv /tmp/$$ "$FILE"
+    git add "$FILE"
+done
+echo Committing change locally.
+git commit -m 'Update copyright year'
+rm -f $ss
diff --git a/release-tools/do-release.pl b/release-tools/do-release.pl
new file mode 100644
index 0000000..1725055
--- /dev/null
+++ b/release-tools/do-release.pl
@@ -0,0 +1,209 @@
+#! /usr/bin/env perl
+# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+use warnings;
+
+my $homedir = glob("~openssl");
+my $tmpdir  = $ENV{"OPENSSL_TMP_DIR"} // $homedir . "/dist/new";
+my $olddir  = $ENV{"OPENSSL_OLD_DIR"} // $homedir . "/dist/old";
+my $srcdir  = $ENV{"OPENSSL_SRC_DIR"} // "/var/www/openssl/source";
+my $ftpdir  = $ENV{"OPENSSL_FTP_DIR"} // "/srv/ftp/source";
+my $mail    = $ENV{"OPENSSL_MAIL"} // "mutt -s SUBJECT RECIP < BODY";
+
+my $do_mail   = 0;
+my $do_copy   = 0;
+my $do_move   = 0;
+my $mail_only = 0;
+
+foreach (@ARGV) {
+    if (/--tmpdir=(.*)$/) {
+        $tmpdir = $1;
+    } elsif (/^--copy$/) {
+        $do_copy = 1;
+    }
+    elsif (/^--move$/) {
+        $do_move = 1;
+    } elsif (/^--mail$/) {
+        $do_mail = 1;
+    } elsif (/^--mail-only$/) {
+        $mail_only = 1;
+        $do_mail   = 1;
+    } elsif (/^--full-release$/) {
+        $do_mail = 1;
+        $do_copy = 1;
+        $do_move = 1;
+    } else {
+        print STDERR "Unknown command line argument $_";
+        exit 1;
+    }
+}
+
+if ( getpwuid($<) ne "openssl" && !exists $ENV{"OPENSSL_RELEASE_TEST"} ) {
+    print "This script must be run as the \"openssl\" user\n";
+    exit 1;
+}
+
+die "Can't find distribution directory $tmpdir"     unless -d $tmpdir;
+die "Can't find old distribution directory $olddir" unless -d $olddir;
+die "Can't find source directory $srcdir"           unless -d $srcdir;
+die "Can't find ftp directory $ftpdir"              unless -d $ftpdir;
+
+my @versions;
+my @series;
+my @files = glob("$tmpdir/*.txt.asc");
+
+foreach (@files) {
+    if (/^.*\/openssl-(\d+\.\d+\.\d+[a-z]*-pre\d+)\..*$/) {
+        push @versions, $1;
+    } elsif (/^.*\/openssl-(\d+\.\d+\.\d+[a-z]*)\..*$/) {
+        push @versions, $1;
+    } else {
+        die "Unexpected filename $_";
+    }
+}
+foreach (@versions) {
+    if (/^(\d+\.\d+\.\d+)[a-z]*$/) {
+        my $serie = $1;
+        push @series, $serie unless grep /^$serie/, @series;
+    }
+}
+die "No distribution in temp directory!" if ( scalar @versions == 0 );
+print "OpenSSL versions to be released:\n";
+foreach (@versions) {
+    print "$_\n";
+}
+print "OK? (y/n)\n";
+$_ = <STDIN>;
+exit 1 unless /^y/i;
+
+my @distfiles;
+my @announce;
+
+foreach (@versions) {
+    push @distfiles, "openssl-$_.tar.gz";
+    push @distfiles, "openssl-$_.tar.gz.sha1";
+    push @distfiles, "openssl-$_.tar.gz.sha256";
+    push @distfiles, "openssl-$_.tar.gz.asc";
+    push @announce,  "openssl-$_.txt.asc";
+}
+
+$do_copy = 0 if $mail_only;
+
+my $bad = 0;
+if ($do_copy) {
+    foreach (@distfiles) {
+        if ( !-f "$tmpdir/$_" ) {
+            print STDERR "File $_ not found in temp directory!\n";
+            $bad = 1;
+        }
+        if ( -e "$srcdir/$_" ) {
+            print STDERR "File $_ already present in source directory!\n";
+            $bad = 1;
+        }
+        if ( -e "$ftpdir/$_" ) {
+            print STDERR "File $_ already present in ftp directory!\n";
+            $bad = 1;
+        }
+        if ( -e "$olddir/$_" ) {
+            print STDERR
+              "File $_ already present in old distributions directory!\n";
+            $bad = 1;
+        }
+    }
+}
+
+exit 1 if $bad;
+
+print "Directory sanity check OK\n";
+
+print "Starting release for OpenSSL @versions\n";
+
+if ($do_copy) {
+    foreach (@distfiles) {
+        system("cp $tmpdir/$_ $srcdir/$_");
+        die "Error copying $_ to source directory!" if $?;
+        system("cp $tmpdir/$_ $ftpdir/$_");
+        die "Error copying $_ to ftp directory!" if $?;
+    }
+    print "Copied distributions files to source and ftp directories\n";
+    foreach my $serie (@series) {
+        my $tomove_oldsrc = "$srcdir/old/$serie";
+        my @tomove_src =
+          map {
+            my $x = $_;
+            $x =~ s|.*/||g;
+            grep( /^$x$/, @distfiles ) ? () : $x
+          }
+          grep { -f $_ }
+          glob("$srcdir/openssl-$serie.tar.gz $srcdir/openssl-$serie?.tar.gz");
+        my $tomove_oldftp = "$ftpdir/old/$serie";
+        my @tomove_ftp =
+          map {
+            my $x = $_;
+            $x =~ s|.*/||g;
+            grep( /^$x$/, @distfiles ) ? () : $x
+          }
+          grep { -f $_ }
+          glob("$ftpdir/openssl-$serie.tar.gz $ftpdir/openssl-$serie?.tar.gz");
+
+        mkdir $tomove_oldsrc
+          or die "Couldn't mkdir $tomove_oldsrc : $!"
+          if !-d $tomove_oldsrc;
+        mkdir $tomove_oldftp
+          or die "Couldn't mkdir $tomove_oldftp : $!"
+          if !-d $tomove_oldftp;
+        foreach (@tomove_src) {
+            system("mv $srcdir/$_* $tomove_oldsrc/");
+            die "Error moving $_* to old source directory!" if $?;
+        }
+        foreach (@tomove_ftp) {
+            system("mv $ftpdir/$_* $tomove_oldftp/");
+            die "Error moving $_* to old ftp directory!" if $?;
+        }
+    }
+    print
+      "Moved old distributions files to source/old and ftp/old directories\n";
+}
+else {
+    print "Test mode: no files copied\n";
+}
+
+foreach (@versions) {
+    my $announce   = "openssl-$_.txt.asc";
+    my $annversion = $_;
+    $annversion =~ s/-pre(\d+$)/ pre release $1/;
+    my $annmail = $mail;
+    $annmail =~ s/SUBJECT/"OpenSSL version $annversion published"/;
+    $annmail =~ s/RECIP/openssl-project openssl-users openssl-announce/;
+    $annmail =~ s|BODY|$tmpdir/$announce|;
+
+    if ($do_mail) {
+        print "Sending announcement email for OpenSSL $_...\n";
+        system("$annmail");
+        die "Error sending announcement email!" if $?;
+        print "Don't forget to authorise the openssl-announce email.\n";
+        push @distfiles, $announce if $do_move;
+    } else {
+        print "Announcement email not sent automatically\n";
+        print "\nSend announcement mail manually with command:\n\n$annmail\n\n";
+        print
+"When done, move the announcement file away with command:\n\nmv $tmpdir/$announce $olddir/$announce\n\n"
+          if $do_move;
+    }
+}
+
+if ($do_move) {
+    foreach (@distfiles) {
+        rename( "$tmpdir/$_", "$olddir/$_" ) || die "Can't move $_: $!";
+    }
+    print "Moved distribution files to old directory\n";
+}
+
+print "Successful!\n";
+
diff --git a/release-tools/mkrelease.pl b/release-tools/mkrelease.pl
new file mode 100644
index 0000000..4012e4d
--- /dev/null
+++ b/release-tools/mkrelease.pl
@@ -0,0 +1,427 @@
+#! /usr/bin/env perl
+# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+# OpenSSL release generation script.
+
+use strict;
+use warnings;
+use File::Basename;
+use lib dirname(__FILE__);
+use Module::Load::Conditional qw(can_load);
+can_load(modules => { 'OpenSSL::Query::DB' => undef });
+use OpenSSL::Query::REST;
+
+require "release-check.pl";
+require "release-date.pl";
+require "release-git.pl";
+require "release-update.pl";
+require "release-version.pl";
+
+our $debug   = 0;
+our $verbose = 0;
+my @reviewers;
+my @openssl_branches;
+my $revert;
+my $pre;
+my $info_only;
+my $branch_info_only;
+my $no_clean;
+my $no_update;
+my $no_release;
+my $no_upload;
+my $bversion;
+my $ok;
+my $label;
+
+#Determine include path
+our $includepath;
+if ( -e "crypto/opensslv.h" ) {
+    $includepath = "crypto";
+}
+else {
+    $includepath = "include/openssl";
+}
+
+sub print_git_info {
+    my ( $rinfo, $branch, $s ) = @_;
+    my $version = openssl_git_expected_version( $rinfo, $branch );
+    my $last = openssl_git_last_release( $rinfo, $branch );
+    my $last_full = openssl_git_last_release( $rinfo, $branch, 1, 1 );
+
+    # Auto detect pre release if we haven't forced it.
+    $pre = $version =~ /-pre/ unless defined $pre;
+    my $next = openssl_version_next( $version, $pre );
+
+    print "${s}Branch version:    $branch\n";
+    print "${s}Last release:      $last\n";
+    print "${s}Last full release: $last_full\n";
+    print "${s}Current version:   $version\n";
+    print "${s}Next release:      $next\n";
+}
+
+sub print_branch_info {
+    my ($rinfo) = @_;
+    my ( $rtags, $rbranches ) = @$rinfo;
+    print "All Branch details:\n";
+    foreach (@$rbranches) {
+        print "\n";
+        print_git_info( $rinfo, $_, "\t" );
+    }
+    print "\n";
+}
+
+# Initialise git version tables, OMC database.
+my $gitinfo = openssl_git_init();
+my $query = OpenSSL::Query->new();
+
+foreach (@ARGV) {
+    if (/^--git-info$/) {
+        $info_only = 1;
+    } elsif (/^--branch-version=(.*)$/) {
+        $bversion = $1;
+    } elsif (/^--git-branch-info/) {
+        $branch_info_only = 1;
+    } elsif (/^--no-clean/) {
+        $no_clean = 1;
+    } elsif (/^--no-release/) {
+        $no_release = 1;
+    } elsif (/^--no-update/) {
+        $no_update = 1;
+    } elsif (/^--no-upload/) {
+        $no_upload = 1;
+    } elsif (/^--revert/) {
+        $revert = 1;
+    } elsif (/^--leave-pre/) {
+        $pre = 0;
+    } elsif (/^--enter-pre/) {
+        $pre = 1;
+    } elsif (/^--debug/) {
+        $debug   = 1;
+        $verbose = 1;
+    } elsif (/^--verbose/) {
+        $verbose = 1;
+    } elsif (/^--reviewer=(.*)$/) {
+	my $r = $1;
+	my $rname = $query->find_person_tag($r, 'rev');
+        die "Unknown reviewer $1" unless $rname;
+        push @reviewers, $rname;
+    } elsif (/^--label=(.*)$/) {
+        $label = $1;
+        if ( $label ne "alpha" && $label ne "beta" ) {
+            die "Invalid label";
+        }
+    } else {
+        print "Uknown option $_\n";
+        exit 1;
+    }
+}
+
+if ($revert) {
+    $_ = openssl_git_current_branch();
+    print "Reverting to repository version for $_\n";
+    system("git reset --hard origin/$_");
+    die "Error reverting!!" if $?;
+    openssl_git_delete_local_tags($_);
+    exit 0;
+}
+
+$bversion = openssl_git_branch_version() unless defined $bversion;
+
+if ($info_only) {
+    print_git_info( $gitinfo, $bversion, "" );
+    exit 0;
+}
+
+if ($branch_info_only) {
+    print_branch_info($gitinfo);
+    exit 0;
+}
+
+die "No reviewer set!" unless @reviewers;
+
+print "Current branch version is $bversion\n";
+
+if ( openssl_git_check_changes() ) {
+    print "ERROR: unstaged changes in current branch!\n";
+    exit 1;
+}
+
+my $expected_version = openssl_git_expected_version( $gitinfo, $bversion );
+
+# If this is first pre release there will be no releases from this branch
+# So set expected version to pre1-dev as we can't detect this from
+# tags.
+
+if ( $expected_version !~ /-pre/ && openssl_check_first_pre() ) {
+    $expected_version =~ s/-dev/-pre1-dev/;
+}
+
+# Auto detect pre release if we haven't forced it.
+$pre = $expected_version =~ /-pre/ unless defined $pre;
+
+if ( !$pre && defined $label ) {
+    die "Not a pre-release but a label has been defined";
+}
+if ( $pre && !defined $label ) {
+    die "This is a pre-release but a label has not been defined";
+}
+
+my $last_version = openssl_git_last_release( $gitinfo, $bversion, 1, 1 );
+my $last_branch_release = openssl_git_last_release( $gitinfo, $bversion, 1 );
+my $next_version = openssl_version_next( $expected_version, $pre );
+
+print "Branch feature version:      $bversion\n";
+print "Last release on this branch: $last_branch_release\n";
+print "Current branch version       $expected_version\n";
+print "Next release version         $next_version\n";
+print "Last full release version    $last_version\n";
+
+$ok = openssl_check_all( $expected_version, $last_version );
+
+print "Branch sanity check: " . ( $ok ? "OK" : "NOT OK" ) . "\n";
+
+if ( $ok == 0 ) {
+    print "Sanity check failed, cannot continue\n";
+    exit 1;
+}
+
+if ( !$no_clean ) {
+    print "Cleaning directory\n";
+    system("git clean -x -d -f");
+    die "Error cleaning directory" if $?;
+}
+
+openssl_git_make_update(@reviewers) unless $no_update;
+
+$expected_version = openssl_version_next( $expected_version, $pre );
+
+my $date = openssl_current_date() unless $expected_version =~ /-pre1-dev/;
+
+print "Updating versions to $expected_version\n";
+
+openssl_update_all( $expected_version, $date, $label );
+
+$ok = openssl_check_all( $expected_version, $last_version, $date );
+
+print "Changes sanity check: " . ( $ok ? "OK" : "NOT OK" ) . "\n";
+
+if ( $ok == 0 ) {
+    print "Release sanity check failed, cannot continue\n";
+    exit 1;
+}
+
+print "Committing changes:\n";
+
+# If we changed from -dev to -pre1-dev a dev version is
+# entering pre release. Just commit changes without a release.
+
+if ( $expected_version =~ /pre1-dev/ ) {
+    my $main_version = $expected_version;
+    $main_version =~ s/-pre1-dev//;
+    openssl_git_commit( "OpenSSL $main_version is now in pre release",
+        @reviewers );
+    die "Error comitting changes!" if $?;
+    print "Version set to $expected_version, exiting\n";
+    exit 0;
+}
+
+openssl_git_commit( "Prepare for $expected_version release", @reviewers );
+die "Error comitting release changes!" if $?;
+
+my $tag = "OpenSSL_$expected_version";
+my $tagkey =
+  defined( $ENV{OPENSSL_GPG_KEYID} ) ? " -u $ENV{OPENSSL_GPG_KEYID}" : " -s";
+
+$tag =~ tr/\./_/;
+
+print
+  "Tagging release with tag $tag (you will need to provide a pass phrase)\n";
+
+system("git tag$tagkey -m \"OpenSSL $expected_version release tag\" $tag");
+die "Error tagging release!" if $?;
+
+my $TAR = defined( $ENV{OPENSSL_TAR} ) ? "TAR=$ENV{OPENSSL_TAR}" : "";
+
+if ( !$no_release ) {
+    print "Generating release tarball.\n";
+    my $openssl = $ENV{"OPENSSL"} // "openssl";
+    my $gpgkeyid =
+      defined( $ENV{OPENSSL_GPG_KEYID} ) ? " -u $ENV{OPENSSL_GPG_KEYID}" : "";
+    my $gpg    = $ENV{"OPENSSL_GPG"}     // "gpg$gpgkeyid";
+    my $gpgtar = $ENV{"OPENSSL_GPG_TAR"} // "$gpg --use-agent -sba";
+    my $gpgann = $ENV{"OPENSSL_GPG_ANNOUNCE"}
+      // "$gpg --use-agent -sta --clearsign";
+    my $tarfile = "openssl-${expected_version}.tar.gz";
+    system("(./config; make $TAR dist) >../$tarfile.log 2>&1");
+    die "Error generating release!" if $?;
+    die "Can't find tarball!!" unless -f "../$tarfile";
+
+    my $length = -s "../$tarfile";
+    print "Creating hash files\n";
+    my $sha1hash = `$openssl sha1 < ../$tarfile`;
+    chomp $sha1hash;
+    $sha1hash =~ s/^.*=\s//;
+    die "invalid hash" unless $sha1hash =~ /[0-9a-f]{20}/;
+    my $sha256hash = `$openssl sha256 < ../$tarfile`;
+    chomp $sha256hash;
+    $sha256hash =~ s/^.*=\s//;
+    die "invalid hash" unless $sha256hash =~ /[0-9a-f]{20}/;
+    open OUT, ">../$tarfile.sha1";
+    print OUT $sha1hash . "\n";
+    close OUT;
+    open OUT, ">../$tarfile.sha256";
+    print OUT $sha256hash . "\n";
+    close OUT;
+    print "Creating PGP signature:\n";
+    unlink("../${tarfile}.asc");
+    system("$gpgtar ../$tarfile");
+    die "Error creating signature" if $?;
+
+    my $anntxt = "../openssl-${expected_version}.txt";
+
+    open OUT, ">$anntxt";
+    if ( $expected_version =~ /-pre/ ) {
+
+        # Note the variable name is the same length as the real
+        # version so the announcement can be made to look pretty.
+        # If we ever go to pre10 it will be one character longer...
+        my $openssl_ver = $expected_version;
+        $openssl_ver =~ s/^(.*)-pre(\d+)$/$1 pre release $2/;
+        my $fvers = $expected_version;
+        $fvers =~ s/-pre\d+//;
+        print OUT <<EOF;
+
+   OpenSSL version $openssl_ver ($label)
+   ===========================================
+
+   OpenSSL - The Open Source toolkit for SSL/TLS
+   https://www.openssl.org/
+
+   OpenSSL $fvers is currently in $label. OpenSSL $openssl_ver has now
+   been made available. For details of changes and known issues see the
+   release notes at:
+
+        https://www.openssl.org/news/openssl-$bversion-notes.html
+
+   Note: This OpenSSL pre-release has been provided for testing ONLY.
+   It should NOT be used for security critical purposes.
+
+   The $label release is available for download via HTTP and FTP from the
+   following master locations (you can find the various FTP mirrors under
+   https://www.openssl.org/source/mirror.html):
+
+     * https://www.openssl.org/source/
+     * ftp://ftp.openssl.org/source/
+
+   The distribution file name is:
+
+    o $tarfile
+      Size: $length
+      SHA1 checksum: $sha1hash
+      SHA256 checksum: $sha256hash
+
+   The checksums were calculated using the following commands:
+
+    openssl sha1 $tarfile
+    openssl sha256 $tarfile
+
+   Please download and check this $label release as soon as possible.
+   To report a bug, open an issue on GitHub:
+
+    ttps://github.com/openssl/openssl/issues
+
+   Please check the release notes and mailing lists to avoid duplicate
+   reports of known issues.
+
+   Yours,
+
+   The OpenSSL Project Team.
+
+EOF
+    } else {
+        # Using $avers so its length is similar to a real version
+        # length so it's easier to make the announcement look pretty.
+        my $avers = $expected_version;
+        print OUT <<EOF;
+
+   OpenSSL version $avers released
+   ===============================
+
+   OpenSSL - The Open Source toolkit for SSL/TLS
+   https://www.openssl.org/
+
+   The OpenSSL project team is pleased to announce the release of
+   version $avers of our open source toolkit for SSL/TLS. For details
+   of changes and known issues see the release notes at:
+
+        https://www.openssl.org/news/openssl-$bversion-notes.html
+
+   OpenSSL $avers is available for download via HTTP and FTP from the
+   following master locations (you can find the various FTP mirrors under
+   https://www.openssl.org/source/mirror.html):
+
+     * https://www.openssl.org/source/
+     * ftp://ftp.openssl.org/source/
+
+   The distribution file name is:
+
+    o $tarfile
+      Size: $length
+      SHA1 checksum: $sha1hash
+      SHA256 checksum: $sha256hash
+
+   The checksums were calculated using the following commands:
+
+    openssl sha1 $tarfile
+    openssl sha256 $tarfile
+
+   Yours,
+
+   The OpenSSL Project Team.
+
+EOF
+
+    }
+
+    close OUT;
+    unlink("${anntxt}.asc");
+    system("$gpgann $anntxt");
+    die "Cannot sign announcement file!" if $?;
+    die "Signature file not found!" unless -f "$anntxt.asc";
+
+    if ( !$no_upload ) {
+        my $scp     = $ENV{OPENSSL_SCP}      // "scp";
+        my $scphost = $ENV{OPENSSL_SCP_HOST} // "dev.openssl.org";
+        my $scpdir  = $ENV{OPENSSL_SCP_DIR}  // "$scphost:~openssl/dist/new";
+        print "Uploading release files\n";
+        system(
+"$scp ../$tarfile ../$tarfile.sha1 ../$tarfile.sha256 ../$tarfile.asc $anntxt.asc ${scpdir}"
+        );
+        die "Error uploading release files" if $?;
+    }
+
+}
+
+$last_version = $expected_version unless $pre;
+$expected_version = openssl_version_next( $expected_version, $pre );
+
+print "Updating versions to $expected_version\n";
+
+openssl_update_all($expected_version);
+
+$ok = openssl_check_all( $expected_version, $last_version );
+
+print "Sanity check: " . ( $ok ? "OK" : "NOT OK" ) . "\n";
+
+if ( $ok == 0 ) {
+    print "Sanity check failed, cannot continue\n";
+    exit 1;
+}
+
+openssl_git_commit( "Prepare for $expected_version", @reviewers );
+die "Error comitting release changes!" if $?;
diff --git a/release-tools/release-check.pl b/release-tools/release-check.pl
new file mode 100644
index 0000000..91ee7c0
--- /dev/null
+++ b/release-tools/release-check.pl
@@ -0,0 +1,215 @@
+#! /usr/bin/env perl
+# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+
+sub check_str {
+    my ( $message, $expected, $value, $pok ) = @_;
+    die "Bad checkstr values for $message"
+      if !defined $value || !defined $expected;
+    if ( $value ne $expected ) {
+        print
+          "$message: check failed, expecting \"$expected\", got \"$value\"!!\n";
+        $$pok = 0;
+    } elsif ($main::debug) {
+        print "$message: checking \"$value\" against \"$expected\"\n";
+    }
+}
+
+# Check syntax of README file.
+
+sub openssl_check_README {
+    my ( $version, $indate ) = @_;
+    my $ok   = 1;
+    my $date = openssl_date($indate);
+    open( IN, "README" ) || die "Can't open README";
+    while (<IN>) {
+        if (/^.*OpenSSL\s+(\S+)\s+(\([[:alpha:]]+\)\s+)?(.*)$/) {
+            check_str( "README version", $version, $1, \$ok );
+            if ( defined $indate ) {
+                check_str( "README date", $date, $3, \$ok );
+            }
+            close IN;
+            return $ok;
+        }
+    }
+    close IN;
+    print STDERR "Invalid syntax in README\n";
+    return 0;
+}
+
+sub openssl_check_NEWS {
+    my ( $version, $prev, $indate ) = @_;
+    my $date = openssl_date( $version =~ /-pre/ ? undef : $indate );
+    my $ok = 1;
+    if ( $date =~ /XXX/ ) {
+        if ( $version =~ /-pre/ ) {
+            $date = "in pre-release";
+        } else {
+            $date = "under development";
+        }
+    }
+    $version =~ s/-dev$//;
+    $version =~ s/-pre.*$//;
+    open( IN, "NEWS" ) || die "Can't open NEWS";
+
+    while (<IN>) {
+        if (
+/^  Major changes between OpenSSL (\S+) and OpenSSL (\S+)\s+\[0?(.*)\]/
+          )
+        {
+            check_str( "NEWS previous version", $prev,    $1, \$ok );
+            check_str( "NEWS version",          $version, $2, \$ok );
+            check_str( "NEWS date",             $date,    $3, \$ok );
+            close IN;
+            return $ok;
+        }
+    }
+    close IN;
+    print STDERR "Invalid syntax in NEWS\n";
+    return 0;
+}
+
+sub openssl_check_CHANGES {
+    my ( $version, $prev, $indate ) = @_;
+    my $date = openssl_date( $version =~ /-pre/ ? undef : $indate );
+    my $ok = 1;
+    $version =~ s/-dev$//;
+    $version =~ s/-pre.*$//;
+    open( IN, "CHANGES" ) || die "Can't open CHANGES";
+
+    while (<IN>) {
+        if (/^ Changes between (\S+) and (\S+)\s+\[0?(.*)\]/) {
+            check_str( "CHANGES previous version", $prev,    $1, \$ok );
+            check_str( "CHANGES version",          $version, $2, \$ok );
+            check_str( "CHANGES date",             $date,    $3, \$ok );
+            close IN;
+            return $ok;
+        }
+    }
+    close IN;
+    print STDERR "Invalid syntax in CHANGES\n";
+    return 0;
+}
+
+sub openssl_check_version_h {
+    my ( $version, $indate ) = @_;
+    my ( $hex_done, $fips_done, $version_done );
+    my $hexversion   = openssl_version_hex($version);
+    my $ok           = 1;
+    my $version_fips = $version . "-fips";
+    $version_fips =~ s/-dev-fips/-fips-dev/;
+    my $date = openssl_date($indate);
+    open( IN, "$main::includepath/opensslv.h" ) || die "Can't open opensslv.h";
+
+    while (<IN>) {
+        if (/OPENSSL_VERSION_NUMBER\s+(0x[0-9a-f]+)L/) {
+            check_str( "opensslv.h: HEX version", $hexversion, $1, \$ok );
+            $hex_done = 1;
+        } elsif (
+/OPENSSL_VERSION_TEXT\s+\"OpenSSL (\S*fips\S*)\s+(\([[:alpha:]]+\)\s+)?(.*)\"/
+          )
+        {
+            check_str( "opensslv.h: FIPS version", $version_fips, $1, \$ok );
+            check_str( "opensslv.h: FIPS date",    $date,         $3, \$ok );
+            $fips_done = 1;
+        } elsif (
+/OPENSSL_VERSION_TEXT\s+\"OpenSSL (\S*)\s+(\([[:alpha:]]+\)\s+)?(.*)\"/
+          )
+        {
+            check_str( "opensslv.h: version", $version, $1, \$ok );
+            check_str( "opensslv.h: date",    $date,    $3, \$ok );
+            $version_done = 1;
+        }
+        if ( $hex_done && $fips_done && $version_done ) {
+            close IN;
+            return $ok;
+        }
+    }
+    print STDERR "Invalid syntax in opensslv.h\n";
+    close IN;
+    return 0;
+}
+
+sub openssl_check_spec {
+    my ($version) = @_;
+    my $ok = 1;
+    $version =~ s/-dev$//;
+    $version =~ s/-pre.*$//;
+    open( IN, "openssl.spec" ) || die "Can't open openssl.spec";
+    while (<IN>) {
+        if (/^Version:\s+(\S+)$/) {
+            check_str( "openssl.spec version", $version, $1, \$ok );
+            close IN;
+            return $ok;
+        }
+    }
+    close IN;
+    print STDERR "Invalid syntax in README\n";
+    return 0;
+}
+
+sub print_ok {
+    my ( $file, $ok ) = @_;
+    print "File: $file " . ( $ok ? "OK" : "NOT OK!!" ) . "\n"
+      if ($main::verbose);
+}
+
+sub openssl_check_all {
+    my ( $version, $last_version, $date ) = @_;
+
+    my $readme_ok = openssl_check_README( $version, $date );
+
+    print_ok( "README", $readme_ok );
+
+    my $changes_ok = openssl_check_CHANGES( $version, $last_version, $date );
+
+    print_ok( "CHANGES", $changes_ok );
+
+    my $news_ok = openssl_check_NEWS( $version, $last_version, $date );
+
+    print_ok( "NEWS", $news_ok );
+
+    my $v_h_ok = openssl_check_version_h( $version, $date );
+
+    print_ok( "opensslv.h", $v_h_ok );
+
+    # Newer versions don't have openssl.spec
+    my $spec_ok = 1;
+    if ( -f "openssl.spec" ) {
+        $spec_ok = openssl_check_spec($version);
+
+        print_ok( "openssl.spec", $spec_ok );
+    }
+
+    return $readme_ok && $changes_ok && $news_ok && $v_h_ok && $spec_ok;
+}
+
+# If there are no tagged releases for the current version
+# and we are in pre release mode then either we are just entering
+# pre release and the next version will be pre1-dev or we are already
+# at pre1-dev and we need to do a release of pre1.
+# Check opensslv.h to determine which
+
+sub openssl_check_first_pre {
+    open( IN, "$main::includepath/opensslv.h" ) || die "Can't open opensslv.h";
+
+    while (<IN>) {
+        if (/OPENSSL_VERSION_TEXT\s+\"OpenSSL \S*\s+.*\"/) {
+            close IN;
+
+            # Ignore -fips in string
+            s/-fips//;
+            return /pre1-dev/;
+        }
+    }
+    close IN;
+    die "Invalid sysntax in opensslv.h";
+}
+
+return 1;
diff --git a/release-tools/release-date.pl b/release-tools/release-date.pl
new file mode 100644
index 0000000..c5b5c38
--- /dev/null
+++ b/release-tools/release-date.pl
@@ -0,0 +1,64 @@
+#! /usr/bin/env perl
+# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+# Return date into a form suitable for the FAQ, version file and
+# CHANGES file entries. Optionally can be passed date in the form
+# mm/dd/yyyy
+
+sub openssl_date {
+    my ($datestr) = @_;
+    my ( $mday, $mon, $year );
+
+    if ( defined $datestr ) {
+        if ( $datestr =~ /(\d+)\/(\d+)\/(\d+)/ ) {
+            $mday = $1;
+            $mon  = $2;
+            $year = $3;
+            $mon--;
+        } else {
+            die "Invalid date syntax $datestr, expecting mm/dd/yyyy";
+        }
+    } else {
+        return ( "xx XXX xxxx", undef, undef ) if wantarray;
+        return "xx XXX xxxx";
+    }
+
+    my $mdsuff;
+    if ( $mday % 10 > 0 && $mday % 10 <= 3 && ( $mday < 10 || $mday > 20 ) ) {
+        my @mday_ord = qw(st nd rd);
+        $mdsuff = $mday_ord[ $mday % 10 - 1 ];
+    } else {
+        $mdsuff = "th";
+    }
+
+    my @mnames =
+      qw(January February March April May June July August September October November December);
+
+    my $mname = $mnames[$mon];
+    my $mname_short = substr $mname, 0, 3;
+
+    my $date_ch = sprintf "%d %s %d", $mday, $mname_short, $year;
+    return $date_ch unless wantarray;
+    my $date_ab = sprintf "%s %d%s, %d", $mname_short, $mday, $mdsuff, $year;
+    my $date_full = sprintf "%-9s %2d%s, %d", $mname, $mday, $mdsuff, $year;
+
+    return ( $date_ch, $date_ab, $date_full );
+
+}
+
+# Return current date in dd/mm/yyyy format suitable to passing into
+# openssl_date().
+
+sub openssl_current_date {
+    my ( $mday, $mon, $year ) = (localtime)[ 3 .. 5 ];
+    $year += 1900;
+    $mon++;
+    return "$mday/$mon/$year";
+}
+
+return 1;
diff --git a/release-tools/release-git.pl b/release-tools/release-git.pl
new file mode 100644
index 0000000..2b6ac1a
--- /dev/null
+++ b/release-tools/release-git.pl
@@ -0,0 +1,164 @@
+#! /usr/bin/env perl
+# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+use warnings;
+
+# OpenSSL git version utilities.
+
+# Retrieve list of branches and release tags in a reference usable by other
+# functions.
+
+sub openssl_git_init {
+    my @tmpbranches =
+      grep { chomp; s|^\s+origin/OpenSSL_(\w*\d)-stable$|$1|; } `git branch -r`;
+    die "Error retrieving branch details!" if $?;
+
+    # Create initial dev version entry: lowest possible version for
+    # branch which will be accurate if no releases have take place.
+    my @branches;
+    foreach ( sort @tmpbranches ) {
+        tr/_/\./;
+        next if /^0/ && $_ ne "0.9.8";
+        push @branches, $_;
+    }
+
+    # Create list of tags
+    my @rtags = grep { chomp; s/OpenSSL_(\d.*)$/$1/; } `git tag`;
+    die "Error retrieving tag details!" if $?;
+    my @tags;
+    foreach (@rtags) {
+
+        # Skip if tag has - and it isn't pre
+        next if ( /-/ && !/-pre\d+$/ );
+        tr/_/\./;
+        next if /^0/ && !/^0.9.8/;
+        push @tags, $_;
+    }
+    my $aref = [ \@tags, \@branches ];
+    return $aref;
+}
+
+# Return last release number on supplied branch.
+# If $nopre is set, skip pre releases, if $prev set
+# return last release on previous branch if no release
+# on current branch.
+
+sub openssl_git_last_release {
+    my ( $rinfo, $branch, $nopre, $prev ) = @_;
+    my ( $rtag, $rbranch ) = @$rinfo;
+    my $brhex = openssl_version_branch_hex($branch);
+    my $rv    = "";
+    my $rvhex = "";
+    foreach (@$rtag) {
+        next if ( $nopre && /-pre/ );
+        my $taghex  = openssl_version_hex($_);
+        my $tagbhex = openssl_version_branch_hex($_);
+
+        # Is tag for current branch?
+        if ( $tagbhex ne $brhex ) {
+
+            # Discard if only want current branch or greater
+            # than current branch
+            next if ( !$prev || $tagbhex gt $brhex );
+        }
+
+        # If release is later than last value replace.
+        if ( $taghex gt $rvhex ) {
+            $rv    = $_;
+            $rvhex = openssl_version_hex($rv);
+        }
+    }
+    return $rv eq "" ? "none" : $rv;
+}
+
+sub openssl_git_current_branch {
+
+    # Current branch
+    $_ = `git rev-parse --abbrev-ref HEAD`;
+    die "Can't get current branch!" if $?;
+    chomp;
+    return $_;
+}
+
+sub openssl_git_branch_version {
+    ($_) = @_;
+    $_ = openssl_git_current_branch() unless defined $_;
+    die "Unexpected  branch name $_" unless s/OpenSSL_//;
+    tr /_/\./;
+    die "Unexpected  branch name $_" unless s/-stable$//;
+    return $_;
+}
+
+sub openssl_git_expected_version {
+    my ( $rinfo, $branch ) = @_;
+    $branch = openssl_git_major_version() unless defined $branch;
+    my $rv = openssl_git_last_release( $rinfo, $branch );
+    return $branch .= "-dev" if $rv eq "none";
+    return openssl_version_next($rv);
+}
+
+sub openssl_git_check_changes {
+
+    # For some reason this is unreliable if you use --quiet ...
+    system("git diff --exit-code >/dev/null");
+    return 0 if $? == 0;
+    return 1 if $? == 256;
+    die "Unexpected status $?";
+}
+
+sub openssl_git_make_update {
+    print "Configuring system\n";
+    system("perl Configure gcc >/dev/null 2>&1");
+    die "Error configuring system" if $?;
+
+    print "Doing make update\n";
+    system("make update >/dev/null 2>&1");
+    die "make update error" if $?;
+    if ( openssl_git_check_changes() ) {
+        print "Source modified, committing changes\n";
+        openssl_git_commit( "make update", @_ );
+        die "Error committing update" if $?;
+    } else {
+        print "No changes\n";
+    }
+    system("find . -name Makefile.save -exec rm \\\{\\\} \\\;");
+    die "Error removing Makefile.save files" if $?;
+}
+
+sub openssl_git_delete_local_tags {
+    my ($branch) = @_;
+    $branch =~ s/-stable//;
+    my @tags = grep { chomp; } `git tag -l $branch\*`;
+    my @rtags =
+      grep { chomp; s|^.*refs/tags/||; } `git ls-remote --tags origin`;
+    my %rtaghash;
+    foreach (@rtags) {
+        $rtaghash{$_} = 1;
+    }
+    foreach (@tags) {
+        if ( !defined $rtaghash{$_} ) {
+            print "Deleting local tag $_\n" if $main::verbose;
+            system("git tag -d $_");
+        }
+    }
+}
+
+sub openssl_git_commit {
+    my @args = ( "git", "commit", "-a" );
+    my ( $message, @reviewers ) = @_;
+    $message .= "\n\n";
+    foreach (@reviewers) {
+        $message .= "Reviewed-by: $_\n";
+    }
+    push @args, "-m", "$message";
+    system(@args);
+    die "Error committing update" if $?;
+}
+
+return 1;
diff --git a/release-tools/release-update.pl b/release-tools/release-update.pl
new file mode 100644
index 0000000..a8d5687
--- /dev/null
+++ b/release-tools/release-update.pl
@@ -0,0 +1,153 @@
+#! /usr/bin/env perl
+# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+use warnings;
+
+sub openssl_update_file {
+    my $fref     = pop @_;
+    my $file     = pop @_;
+    my $file_new = $file . ".new";
+    my $finished = 0;
+    open( IN,  "$file" )      || die "Can't open $file";
+    open( OUT, ">$file_new" ) || die "Can't open $file_new";
+    while (<IN>) {
+        $finished = &$fref(@_) unless $finished;
+        print OUT;
+    }
+    close IN;
+    close OUT;
+    unlink $file;
+    rename $file_new, $file;
+    print "Updated $file\n" if $main::verbose;
+}
+
+sub openssl_update_README {
+    my ( $version, $indate, $label ) = @_;
+    my $date   = openssl_date($indate);
+    my $update = sub {
+        if (/^.*OpenSSL/) {
+            $_ = " OpenSSL $version";
+            $_ .= " $label" if ( defined $label );
+            $_ .= " $date"  if ( defined $indate );
+            $_ .= "\n";
+            return 1;
+        }
+        return 0;
+    };
+    openssl_update_file( @_, "README", $update );
+}
+
+sub openssl_update_CHANGES {
+    my ( $version, $indate ) = @_;
+    my $date = openssl_date($indate);
+    $version =~ s/-dev//;
+    my $update = sub {
+        if (/^ Changes between \S+ and (\S+)\s+\[0?(.*)\]/) {
+            my $chversion = $1;
+            my $chdate    = $2;
+            if ( defined $indate ) {
+                s/$chdate/$date/;
+            } else {
+                my $newchanges = <<END;
+ Changes between $chversion and $version [xx XXX xxxx]
+
+  *)
+
+END
+                $_ = $newchanges . $_;
+            }
+            return 1;
+        }
+        return 0;
+    };
+    openssl_update_file( @_, "CHANGES", $update );
+}
+
+sub openssl_update_NEWS {
+    my ( $version, $indate ) = @_;
+    my $date;
+    if ( $version =~ /-pre1-dev/ ) {
+        $date   = "in pre-release";
+        $indate = "";
+    } elsif ( $version =~ /-pre/ ) {
+        return 1;
+    } else {
+        $date = openssl_date($indate);
+    }
+    $version =~ s/-dev//;
+    my $update = sub {
+        if (
+/^  Major changes between OpenSSL \S+ and OpenSSL (\S+)\s+\[0?(.*)\]/
+          )
+        {
+            my $chversion = $1;
+            my $chdate    = $2;
+            if ( defined $indate ) {
+                s/$chdate/$date/;
+            } else {
+                my $newchanges = <<END;
+  Major changes between OpenSSL $chversion and OpenSSL $version [under development]
+
+      o
+
+END
+                $_ = $newchanges . $_;
+            }
+            return 1;
+        }
+        return 0;
+    };
+    openssl_update_file( @_, "NEWS", $update );
+}
+
+sub openssl_update_version_h {
+    my ( $version, $indate, $label ) = @_;
+    my $hexversion   = openssl_version_hex($version);
+    my $date         = openssl_date($indate);
+    my $version_fips = $version . "-fips";
+    $version_fips =~ s/-dev-fips/-fips-dev/;
+    if ( !defined $label ) {
+        $label = "";
+    }
+    my $update = sub {
+        if (/(#\s*define\s+OPENSSL_VERSION_NUMBER\s+)/) {
+            $_ = "${1}${hexversion}L\n";
+        } elsif (/(#\s*define\s+OPENSSL_VERSION_TEXT\s+).*fips/) {
+            $_ = "${1}\"OpenSSL $version_fips $label $date\"\n";
+        } elsif (/(#\s*define\s+OPENSSL_VERSION_TEXT\s+)/) {
+            $_ = "${1}\"OpenSSL $version $label $date\"\n";
+        }
+        return 0;
+    };
+    openssl_update_file( @_, "$main::includepath/opensslv.h", $update );
+}
+
+sub openssl_update_spec {
+    my ($version) = @_;
+    $version =~ s/-dev$//;
+    my $update = sub {
+        s/^Version:\s+(\S+)$/Version: $version/;
+    };
+    openssl_update_file( @_, "openssl.spec", $update );
+}
+
+sub openssl_update_all {
+    my ( $version, $date, $label ) = @_;
+    my $ispre = $version =~ /-pre/;
+    if ( defined $label ) {
+        $label = "($label)";
+    }
+    openssl_update_version_h( $version, $date, $label );
+    openssl_update_spec($version) if ( !$ispre && -f "openssl.spec" );
+    openssl_update_README( $version, $date, $label );
+    openssl_update_CHANGES( $version, $date ) unless $ispre;
+    openssl_update_NEWS( $version, $date );
+}
+
+return 1;
diff --git a/release-tools/release-version.pl b/release-tools/release-version.pl
new file mode 100644
index 0000000..3e163b0
--- /dev/null
+++ b/release-tools/release-version.pl
@@ -0,0 +1,179 @@
+#! /usr/bin/env perl
+# Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+use warnings;
+
+# OpenSSL version utility functions.
+
+# Convert string version to hex format
+# usage is version_hex($version_string, $tag)
+# where "tag" is 1 if the version comes from a git tag.
+# Return version in hex format.
+
+sub openssl_version_hex {
+    my ( $version, $tag ) = @_;
+    my $ov = $version;
+    $tag = $version =~ /_/ unless defined $tag;
+    $version =~ tr/_/\./ if $tag;
+
+    # Separate version string into fields and convert each one.
+
+    if ( !( $version =~ /([\d])\.([\d]+).([\d]+)(.*)$/ ) ) {
+        die "Invalid version syntax \"$version\"";
+    }
+    my $M    = $1;
+    my $NN   = sprintf "%02x", $2;
+    my $FF   = sprintf "%02x", $3;
+    my $rest = $4;
+
+    if ( length $M > 1 || length $NN > 2 || length $FF > 2 ) {
+        die "Invalid version syntax";
+    }
+
+    my ( $PP, $S );
+
+    if ( $rest eq "" ) {
+        $PP = "00";
+        $S  = "f";
+    } else {
+        $S = "";
+        if ( $rest =~ s/-dev$// ) {
+            $S = "0";
+        }
+
+        # Note pre release development versions of the form -preX-dev
+        # version is same for pre release and development versions
+        # So check for -preX after we have stripped off any
+        # -dev above.
+        if ( $rest =~ s/-pre([\d]+)$// ) {
+            $S = sprintf "%x", $1;
+        }
+
+        # No -dev or -pre, must be release
+        $S = "f" if $S eq "";
+
+        if ( $rest eq "" ) {
+            $PP = "00";
+        } elsif ( $rest =~ /^z([a-z]$)/ ) {
+            $PP = sprintf "%02x", ord($1) - ord("a") + 26;
+        } elsif ( $rest =~ /(^[a-z]$)/ ) {
+            $PP = sprintf "%02x", ord($1) - ord("a") + 1;
+        } else {
+            die "Invalid version syntax: \"$ov\"";
+        }
+    }
+
+    if ( length $S > 1 || length $PP > 2 ) {
+        die "Invalid version syntax";
+    }
+
+    return "0x$M$NN$FF$PP$S";
+
+}
+
+# Convert hex format to string
+# Usage is version_str($hex_version), returns version as a string.
+
+sub openssl_version_str {
+    my ($hexversion) = @_;
+    my ( $chk, $M, $NN, $FF, $PP, $S ) = unpack "A2AA2A2A2A", $hexversion;
+    die "Bad hex version $hexversion" if $chk ne "0x" || $S eq "";
+    my $version_str = hex($M) . "." . hex($NN) . "." . hex($FF);
+
+    if ( $PP ne "00" ) {
+        my $hex_PP = hex($PP);
+        if ( $hex_PP > 25 ) {
+            $version_str .= "z";
+            $hex_PP -= 25;
+        }
+        $version_str .= chr( $hex_PP + ord("a") - 1 );
+    }
+
+    if ( $S eq "0" ) {
+        $version_str .= "-dev";
+    } elsif ( $S ne "f" ) {
+        $version_str .= "-pre" . hex($S);
+    }
+
+    return $version_str;
+
+}
+
+# Given a hex number work out the next version.
+# Usage is openssl_next_version($version, $pre, $dev)
+# $pre indicates whether we should use pre releases
+# $dev indicates we should use a development version.
+
+sub openssl_version_next {
+    my ( $version, $pre, $dev ) = @_;
+    my $hexversion = openssl_version_hex($version);
+    my ( $chk, $M, $NN, $FF, $PP, $S ) = unpack "A2AA2A2A2A", $hexversion;
+    die "Invalid syntax $version" if $S eq "";
+
+    # If $pre or $dev not set work out what we want.
+    $dev = $version !~ /-dev/ unless defined $dev;
+    $pre = $version =~ /-pre/ unless defined $pre;
+
+    # If we want a release then just need to get rid of "-dev" part.
+    #
+    if ( $dev == 0 ) {
+        die "Expecting a development version!!" if $version !~ /-dev/;
+
+        # NB version number is identical for pre and pre development.
+        # So just strip out "-dev" part.
+        $version =~ s/-dev//;
+
+        # Special case: if we are going from X.Y.Z-dev and using pre releases
+        # next version is X.Y.Z-pre1-dev and this wont be a release,
+        # just changing version numbers for beginning of pre releases.
+        $version .= "-pre1-dev" if $pre && $S eq "0";
+
+        # If moving out of pre release return full release
+        $version =~ s/-pre.*$// unless $pre;
+        return $version;
+    }
+    die "Not expecting a development version!!" if $version =~ /-dev/;
+
+    # If a pre release we need to increment the pre release portion
+    if ( $pre != 0 ) {
+
+        # Hex version can only handle 14 pre releases.
+        die "Can't go past pre release 14!!" if ( $S eq "e" );
+
+        # Must be a pre release or development version.
+        die "Can't go from release to pre release!!" if $S eq "f";
+        $S = sprintf "%x", hex($S) + 1;
+        $hexversion =~ s/.$/$S/;
+        $version = openssl_version_str($hexversion);
+        $version .= "-dev" if $dev;
+        return $version;
+    }
+
+   # If last version pre release and not doing pre releases any more then switch
+   # to full release.
+    return openssl_version_str("0x$M$NN$FF${PP}f") if ( $version =~ /pre/ );
+
+    # Otherwise need to increment letter value if not a pre release.
+    $PP = sprintf "%02x", hex($PP) + 1;
+    die "Invalid letter version!!" if ( length $PP > 2 );
+    return openssl_version_str("0x$M$NN$FF${PP}0");
+}
+
+# Return hex branch version belongs to.
+# So "1.0.1a-pre2-dev" returns hex of "1.0.1" for example.
+
+sub openssl_version_branch_hex {
+    my ($version) = @_;
+    my $hexversion = openssl_version_hex($version);
+    my ( $chk, $M, $NN, $FF, $PP, $S ) = unpack "A2AA2A2A2A", $hexversion;
+    die "Invalid syntax $version" if $S eq "";
+    return "0x$M$NN${FF}00F";
+}
+
+return 1;


More information about the openssl-commits mailing list