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