1#!/bin/bash 2# 3# Copyright (C) 2010 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18# 19# This script imports new versions of Bouncy Castle 20# (http://bouncycastle.org) into the Android source tree. To run, (1) 21# fetch the appropriate tarballs (bcprov and bcpkix) from the Bouncy 22# Castle repository, (2) check the checksum, and then (3) run: 23# ./import_bouncycastle.sh import bcprov-jdk*-*.tar.gz 24# 25# IMPORTANT: See README.android for additional details. 26 27# turn on exit on error as well as a warning when it happens 28set -e 29trap "echo WARNING: Exiting on non-zero subprocess exit code" ERR; 30 31function die() { 32 declare -r message=$1 33 34 echo $message 35 exit 1 36} 37 38function usage() { 39 declare -r message=$1 40 41 if [ ! "$message" = "" ]; then 42 echo $message 43 fi 44 echo "Usage:" 45 echo " ./import_bouncycastle.sh import </path/to/bcprov-jdk*-*.tar.gz>" 46 echo " ./import_bouncycastle.sh regenerate <patch/*.patch>" 47 echo " ./import_bouncycastle.sh generate <patch/*.patch> </path/to/bcprov-jdk*-*.tar.gz>" 48 exit 1 49} 50 51function main() { 52 if [ ! -d patches ]; then 53 die "Bouncy Castle patch directory patches/ not found" 54 fi 55 56 if [ ! -f bouncycastle.version ]; then 57 die "bouncycastle.version not found" 58 fi 59 60 source bouncycastle.version 61 if [ "$BOUNCYCASTLE_JDK" == "" -o "$BOUNCYCASTLE_VERSION" == "" ]; then 62 die "Invalid bouncycastle.version; see README.android for more information" 63 fi 64 65 BOUNCYCASTLE_BCPROV_DIR=bcprov-jdk$BOUNCYCASTLE_JDK-$BOUNCYCASTLE_VERSION 66 BOUNCYCASTLE_BCPROV_DIR_ORIG=$BOUNCYCASTLE_BCPROV_DIR.orig 67 68 BOUNCYCASTLE_BCPKIX_DIR=bcpkix-jdk$BOUNCYCASTLE_JDK-$BOUNCYCASTLE_VERSION 69 BOUNCYCASTLE_BCPKIX_DIR_ORIG=$BOUNCYCASTLE_BCPKIX_DIR.orig 70 71 if [ ! -f bouncycastle.config ]; then 72 die "bouncycastle.config not found" 73 fi 74 75 source bouncycastle.config 76 if [ "$UNNEEDED_BCPROV_SOURCES" == "" -o "$NEEDED_BCPROV_SOURCES" == "" \ 77 -o "$UNNEEDED_BCPKIX_SOURCES" == "" -o "$NEEDED_BCPKIX_SOURCES" == "" ]; then 78 die "Invalid bouncycastle.config; see README.android for more information" 79 fi 80 81 declare -r command=$1 82 shift || usage "No command specified. Try import, regenerate, or generate." 83 if [ "$command" = "import" ]; then 84 declare -r bcprov_tar=$1 85 shift || usage "No tar file specified." 86 declare -r bcpkix_tar=`echo $bcprov_tar | sed s/bcprov/bcpkix/` 87 import $bcprov_tar $BOUNCYCASTLE_BCPROV_DIR $BOUNCYCASTLE_BCPROV_DIR_ORIG bcprov "$BOUNCYCASTLE_BCPROV_PATCHES" "$NEEDED_BCPROV_SOURCES" "$UNNEEDED_BCPROV_SOURCES" 88 import $bcpkix_tar $BOUNCYCASTLE_BCPKIX_DIR $BOUNCYCASTLE_BCPKIX_DIR_ORIG bcpkix "$BOUNCYCASTLE_BCPKIX_PATCHES" "$NEEDED_BCPKIX_SOURCES" "$UNNEEDED_BCPKIX_SOURCES" 89 elif [ "$command" = "regenerate" ]; then 90 declare -r patch=$1 91 shift || usage "No patch file specified." 92 if [[ $BOUNCYCASTLE_BCPROV_PATCHES == *$patch* ]]; then 93 [ -d $BOUNCYCASTLE_BCPROV_DIR ] || usage "$BOUNCYCASTLE_BCPROV_DIR not found, did you mean to use generate?" 94 [ -d $BOUNCYCASTLE_BCPROV_DIR_ORIG ] || usage "$BOUNCYCASTLE_BCPROV_DIR_ORIG not found, did you mean to use generate?" 95 regenerate $patch $BOUNCYCASTLE_BCPROV_DIR $BOUNCYCASTLE_BCPROV_DIR_ORIG 96 elif [[ $BOUNCYCASTLE_BCPKIX_PATCHES == *$patch* ]]; then 97 [ -d $BOUNCYCASTLE_BCPKIX_DIR ] || usage "$BOUNCYCASTLE_BCPROV_DIR not found, did you mean to use generate?" 98 [ -d $BOUNCYCASTLE_BCPKIX_DIR_ORIG ] || usage "$BOUNCYCASTLE_BCPKIX_DIR_ORIG not found, did you mean to use generate?" 99 regenerate $patch $BOUNCYCASTLE_BCPKIX_DIR $BOUNCYCASTLE_BCPKIX_DIR_ORIG 100 else 101 usage "Unknown patch file $patch specified" 102 fi 103 elif [ "$command" = "generate" ]; then 104 declare -r patch=$1 105 shift || usage "No patch file specified." 106 declare -r bcprov_tar=$1 107 shift || usage "No tar file specified." 108 declare -r bcpkix_tar=`echo $bcprov_tar | sed s/bcprov/bcpkix/` 109 if [[ $BOUNCYCASTLE_BCPROV_PATCHES == *$patch* ]]; then 110 generate $patch $bcprov_tar $BOUNCYCASTLE_BCPROV_DIR $BOUNCYCASTLE_BCPROV_DIR_ORIG bcprov "$BOUNCYCASTLE_BCPROV_PATCHES" "$NEEDED_BCPROV_SOURCES" "$UNNEEDED_BCPROV_SOURCES" 111 elif [[ $BOUNCYCASTLE_BCPKIX_PATCHES == *$patch* ]]; then 112 generate $patch $bcpkix_tar $BOUNCYCASTLE_BCPKIX_DIR $BOUNCYCASTLE_BCPKIX_DIR_ORIG bcpkix "$BOUNCYCASTLE_BCPKIX_PATCHES" "$NEEDED_BCPKIX_SOURCES" "$UNNEEDED_BCPKIX_SOURCES" 113 else 114 usage "Unknown patch file $patch specified" 115 fi 116 else 117 usage "Unknown command specified $command. Try import, regenerate, or generate." 118 fi 119} 120 121function import() { 122 declare -r bouncycastle_source=$1 123 declare -r bouncycastle_dir=$2 124 declare -r bouncycastle_dir_orig=$3 125 declare -r bouncycastle_out_dir=$4 126 declare -r bouncycastle_patches=$5 127 declare -r needed_sources=$6 128 declare -r unneeded_sources=$7 129 130 untar $bouncycastle_source $bouncycastle_dir $bouncycastle_dir_orig "$unneeded_sources" 131 applypatches $bouncycastle_dir "$bouncycastle_patches" "$unneeded_sources" 132 133 cd $bouncycastle_dir 134 135 sed 's/<p>/& <BR>/g' LICENSE.html | html2text -width 102 -nobs -ascii > ../NOTICE 136 touch ../MODULE_LICENSE_BSD_LIKE 137 138 cd .. 139 140 rm -r $bouncycastle_out_dir/src 141 mkdir -p $bouncycastle_out_dir/src/main/java/ 142 for i in $needed_sources; do 143 echo "Updating $i" 144 mv $bouncycastle_dir/$i $bouncycastle_out_dir/src/main/java/ 145 done 146 147 cleantar $bouncycastle_dir $bouncycastle_dir_orig 148} 149 150function regenerate() { 151 declare -r patch=$1 152 declare -r bouncycastle_dir=$2 153 declare -r bouncycastle_dir_orig=$3 154 155 generatepatch $patch $bouncycastle_dir $bouncycastle_dir_orig 156} 157 158function update_timestamps() { 159 declare -r git_dir="$1" 160 declare -r target_dir="$2" 161 162 echo -n "Restoring timestamps for ${target_dir}... " 163 164 find "$git_dir" -type f -print0 | while IFS= read -r -d $'\0' file; do 165 file_rev="$(git rev-list -n 1 HEAD "$file")" 166 if [ "$file_rev" == "" ]; then 167 echo 168 echo -n "WARNING: No file revision for file $file..." 169 continue 170 fi 171 file_time="$(git show --pretty=format:%ai --abbrev-commit "$file_rev" | head -n 1)" 172 touch -d "$file_time" "${target_dir}${file#$git_dir}" 173 done 174 175 echo "done." 176} 177 178function generate() { 179 declare -r patch=$1 180 declare -r bouncycastle_source=$2 181 declare -r bouncycastle_dir=$3 182 declare -r bouncycastle_dir_orig=$4 183 declare -r bouncycastle_out_dir=$5 184 declare -r bouncycastle_patches=$6 185 declare -r needed_sources=$7 186 declare -r unneeded_sources=$8 187 188 untar $bouncycastle_source $bouncycastle_dir $bouncycastle_dir_orig "$unneeded_sources" 189 applypatches $bouncycastle_dir "$bouncycastle_patches" "$unneeded_sources" 190 191 for i in $needed_sources; do 192 echo "Restoring $i" 193 rm -r $bouncycastle_dir/$i 194 cp -rf $bouncycastle_out_dir/src/main/java/$i $bouncycastle_dir/$i 195 update_timestamps $bouncycastle_out_dir/src/main/java/$i $bouncycastle_dir/$i 196 done 197 198 generatepatch $patch $bouncycastle_dir $bouncycastle_dir_orig 199 cleantar $bouncycastle_dir $bouncycastle_dir_orig 200} 201 202function untar() { 203 declare -r bouncycastle_source=$1 204 declare -r bouncycastle_dir=$2 205 declare -r bouncycastle_dir_orig=$3 206 declare -r unneeded_sources=$4 207 208 # Remove old source 209 cleantar $bouncycastle_dir $bouncycastle_dir_orig 210 211 # Process new source 212 tar -zxf $bouncycastle_source 213 mv $bouncycastle_dir $bouncycastle_dir_orig 214 find $bouncycastle_dir_orig -type f -print0 | xargs -0 chmod a-w 215 (cd $bouncycastle_dir_orig && unzip -q src.zip) 216 tar -zxf $bouncycastle_source 217 (cd $bouncycastle_dir && unzip -q src.zip) 218 219 # Prune unnecessary sources 220 echo "Removing $unneeded_sources" 221 (cd $bouncycastle_dir_orig && rm -rf $unneeded_sources) 222 (cd $bouncycastle_dir && rm -r $unneeded_sources) 223} 224 225function cleantar() { 226 declare -r bouncycastle_dir=$1 227 declare -r bouncycastle_dir_orig=$2 228 229 rm -rf $bouncycastle_dir_orig 230 rm -rf $bouncycastle_dir 231} 232 233function applypatches () { 234 declare -r bouncycastle_dir=$1 235 declare -r bouncycastle_patches=$2 236 declare -r unneeded_sources=$3 237 238 cd $bouncycastle_dir 239 240 # Apply appropriate patches 241 for i in $bouncycastle_patches; do 242 echo "Applying patch $i" 243 patch -p1 --merge < ../$i || die "Could not apply patches/$i. Fix source and run: $0 regenerate $i" 244 245 # make sure no unneeded sources got into the patch 246 problem=0 247 for s in $unneeded_sources; do 248 if [ -e $s ]; then 249 echo Unneeded source $s restored by patch $i 250 problem=1 251 fi 252 done 253 if [ $problem = 1 ]; then 254 exit 1 255 fi 256 done 257 258 # Cleanup patch output 259 find . -type f -name "*.orig" -print0 | xargs -0 rm -f 260 261 cd .. 262} 263 264function generatepatch() { 265 declare -r patch=$1 266 declare -r bouncycastle_dir=$2 267 declare -r bouncycastle_dir_orig=$3 268 269 # Cleanup stray files before generating patch 270 find $bouncycastle_dir -type f -name "*.orig" -print0 | xargs -0 rm -f 271 find $bouncycastle_dir -type f -name "*~" -print0 | xargs -0 rm -f 272 273 rm -f $patch 274 LC_ALL=C TZ=UTC0 diff -Naur $bouncycastle_dir_orig $bouncycastle_dir >> $patch && die "ERROR: No diff for patch $path in file $i" 275 echo "Generated patch $patch" 276} 277 278main $@ 279