rsa-encrypt-decrypt-sign-verify.sh 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. #!/bin/bash
  2. ##############################################################################
  3. # Copyright (c) 2021 by Rambus, Inc. and/or its subsidiaries
  4. # All rights reserved. Unauthorized use (including, without limitation,
  5. # distribution and copying) is strictly prohibited. All use requires,
  6. # and is subject to, explicit written authorization and nondisclosure
  7. # Rambus, Inc. and/or its subsidiaries
  8. #
  9. # For more information or support, please go to our online support system at
  10. # https://sipsupport.rambus.com.
  11. # In case you do not have an account for this system, please send an e-mail
  12. # to sipsupport@rambus.com.
  13. ##############################################################################
  14. ############################ constants ############################
  15. DATESTAMP=$(date +%y%m%d_%H%M)
  16. TEMPFILE=tempfile.txt
  17. VALGRIND_CMD='valgrind --leak-check=full --show-leak-kinds=all --log-file='$TEMPFILE
  18. # configure based engine id
  19. engine_id=eip28pka
  20. ############################ functions ############################
  21. if [ -z "${OPENSSL_DIR}" ]; then
  22. echo "Error: OPENSSL_DIR not set."
  23. echo "Please let an environment named OPENSSL_DIR refer to the"
  24. echo "directory where the OpenSSL package was built, such that"
  25. echo "\${OPENSSL_DIR}/apps/openssl refers to the openssl app to use."
  26. exit 1
  27. fi
  28. # Run various test with the following instance of OpenSSL.
  29. OSSL=${OPENSSL_DIR}/apps/openssl
  30. if [ ! -x ${OSSL} ]; then
  31. echo "Error: ${OSSL} not found or not executable?!"
  32. exit 1
  33. fi
  34. # Pad `file` such that its size equals `target_size`.
  35. padd_file () {
  36. local file=$1
  37. local target_size=$2
  38. local padding="++++++++"
  39. local text=$(cat ${file})
  40. while (( ${#padding} < ${target_size} )); do
  41. padding="${padding}${padding}"
  42. done
  43. echo "${padding}${text}" | tail --bytes ${target_size} - > ${file}
  44. }
  45. # Generate an RSA keypair of the specified size and store
  46. # it in the specified .pem file.
  47. ossl_gen_rsa_key () {
  48. local nbits=$1
  49. local keyfile=$2
  50. local keyform=${keyfile##*.}
  51. if [[ "${keyform}" != "pem" ]]; then
  52. echo "ossl_gen_rsa_key: filename must end with .pem"
  53. else
  54. ${OSSL} genpkey -out ${keyfile} -outform ${keyform} \
  55. -algorithm RSA -pkeyopt rsa_keygen_bits:${nbits}
  56. fi
  57. }
  58. # Show the RSA keypair stored in the specified .pem or .der file.
  59. ossl_show_rsa_key () {
  60. local keyfile=$1
  61. local keyform=${keyfile##*.}
  62. if [[ "${keyform}" != "pem" && "${keyform}" != "der" ]]; then
  63. echo "ossl_show_key: filename must end with .der or .pem"
  64. else
  65. if [[ "${keyform}" == "pem" ]]; then
  66. # Convert .pem to .der
  67. ${OSSL} rsa -out __@der@__ -outform der -in ${keyfile}
  68. ${OSSL} asn1parse -in __@der@__ -inform der
  69. rm -f __@der@__
  70. else
  71. ${OSSL} asn1parse -in ${keyfile} -inform ${keyform}
  72. fi
  73. fi
  74. }
  75. # Use the indicated RSA scheme (pkcs1 or pss) to sign the given
  76. # `msgfile`, with the (private) RSA key coming from `keyfile` and
  77. # store the signature in `sigfile`.
  78. # For the moment, the hash algorithm used is always SHA256.
  79. ossl_rsa_sign () {
  80. local msgfile=$1
  81. local keyfile=$2
  82. local sigfile=$3
  83. local padding=$4 # pkcs1 or pss
  84. local keyform=${keyfile##*.}
  85. local opt_saltlen=""
  86. local hashalg="sha256"
  87. if [[ "${padding}" == "pss" ]]; then
  88. opt_saltlen="-pkeyopt rsa_pss_saltlen:32"
  89. fi
  90. ${OSSL} dgst -${hashalg} -out __@hash@__ -binary ${msgfile}
  91. ${OSSL} pkeyutl -sign -out ${sigfile} -in __@hash@__ \
  92. -inkey ${keyfile} -keyform ${keyform} \
  93. -pkeyopt rsa_padding_mode:${padding} \
  94. -pkeyopt digest:${hashalg} ${opt_saltlen}
  95. rm -f __@hash@__
  96. }
  97. # Use the indicated RSA scheme (pkcs1 or pss) to verify if the
  98. # signature in `sigfile` matches the given `msgfile`, with the
  99. # (public) RSA key coming from `keyfile`.
  100. # For the moment, the hash algorithm used is always SHA256.
  101. ossl_rsa_vrfy() {
  102. local msgfile=$1
  103. local keyfile=$2
  104. local sigfile=$3
  105. local verfile=$4
  106. local padding=$5
  107. local keyform=${keyfile##*.}
  108. local opt_saltlen=""
  109. local hashalg="sha256"
  110. if [[ "${padding}" == "pss" ]]; then
  111. opt_saltlen="-pkeyopt rsa_pss_saltlen:32"
  112. fi
  113. ${OSSL} dgst -${hashalg} -out __@hash@__ -binary ${msgfile}
  114. ${OSSL} pkeyutl -verify -in __@hash@__ -sigfile ${sigfile} \
  115. -inkey ${keyfile} -keyform ${keyform} \
  116. -pkeyopt rsa_padding_mode:${padding} \
  117. -pkeyopt digest:${hashalg} ${opt_saltlen} \
  118. -out ${verfile}
  119. rm -f __@hash@__
  120. }
  121. # Use the indicated RSA scheme (pkcs1 or pss) to sign the given
  122. # `msgfile`, with the (private) RSA key coming from `keyfile` and
  123. # store the signature in `sigfile`.
  124. # For the moment, the hash algorithm used is always SHA256.
  125. ossl_engine_rsa_sign () {
  126. local msgfile=$1
  127. local keyfile=$2
  128. local sigfile=$3
  129. local padding=$4 # pkcs1 or pss
  130. local keyform=${keyfile##*.}
  131. local opt_saltlen=""
  132. local hashalg="sha256"
  133. if [[ "${padding}" == "pss" ]]; then
  134. opt_saltlen="-pkeyopt rsa_pss_saltlen:32"
  135. fi
  136. if [ $DO_VALGRIND ]; then
  137. echo "// ossl_engine_rsa_sign $2 $3 $4" >> rsa-encrypt-decrypt-sign-verify_$DATESTAMP.log
  138. fi
  139. ${OSSL} dgst -${hashalg} -out __@hash@__ -binary ${msgfile}
  140. $VALGRIND ${OSSL} pkeyutl -engine ${engine_id} -sign -out ${sigfile} -in __@hash@__ \
  141. -inkey ${keyfile} -keyform ${keyform} \
  142. -pkeyopt rsa_padding_mode:${padding} \
  143. -pkeyopt digest:${hashalg} ${opt_saltlen}
  144. if [ $DO_VALGRIND ]; then
  145. cat $TEMPFILE >> rsa-encrypt-decrypt-sign-verify_$DATESTAMP.log
  146. fi
  147. rm -f __@hash@__
  148. }
  149. # Use the indicated RSA scheme (pkcs1 or pss) to verify if the
  150. # signature in `sigfile` matches the given `msgfile`, with the
  151. # (public) RSA key coming from `keyfile`.
  152. # For the moment, the hash algorithm used is always SHA256.
  153. ossl_engine_rsa_vrfy() {
  154. local msgfile=$1
  155. local keyfile=$2
  156. local sigfile=$3
  157. local verfile=$4
  158. local padding=$5
  159. local keyform=${keyfile##*.}
  160. local opt_saltlen=""
  161. local hashalg="sha256"
  162. if [[ "${padding}" == "pss" ]]; then
  163. opt_saltlen="-pkeyopt rsa_pss_saltlen:32"
  164. fi
  165. if [ $DO_VALGRIND ]; then
  166. echo "// ossl_engine_rsa_vrfy $2 $3 $4 $5" >> rsa-encrypt-decrypt-sign-verify_$DATESTAMP.log
  167. fi
  168. ${OSSL} dgst -${hashalg} -out __@hash@__ -binary ${msgfile}
  169. $VALGRIND ${OSSL} pkeyutl -engine ${engine_id} -verify -in __@hash@__ -sigfile ${sigfile} \
  170. -inkey ${keyfile} -keyform ${keyform} \
  171. -pkeyopt rsa_padding_mode:${padding} \
  172. -pkeyopt digest:${hashalg} ${opt_saltlen} \
  173. -out ${verfile}
  174. if [ $DO_VALGRIND ]; then
  175. cat $TEMPFILE >> rsa-encrypt-decrypt-sign-verify_$DATESTAMP.log
  176. fi
  177. rm -f __@hash@__
  178. }
  179. # Use the indicated RSA scheme (none, pkcs1 or oaep) to encrypt the given
  180. # `ptxfile`, with the (public) RSA key coming from `keyfile` and
  181. # store the cryptogram in `ctxfile`.
  182. ossl_rsa_encrypt () {
  183. local ptxfile=$1
  184. local keyfile=$2
  185. local ctxfile=$3
  186. local padding=$4 # none, pkcs1 or oaep
  187. local hashalg="sha1"
  188. local keyform=${keyfile##*.}
  189. local opt_mgf1_md=""
  190. local opt_digest=""
  191. if [[ "${padding}" == "oaep" ]]; then
  192. :
  193. # opt_mgf1_md="-pkeyopt rsa_mgf1_md:${hashalg}"
  194. # opt_digest="-pkeyopt digest:${hashalg}"
  195. fi
  196. ${OSSL} pkeyutl -encrypt -out ${ctxfile} -in ${ptxfile} \
  197. -inkey ${keyfile} -keyform ${keyform} \
  198. -pkeyopt rsa_padding_mode:${padding} ${opt_mgf1_md} ${opt_digest}
  199. }
  200. # Use the indicated RSA scheme (none, pkcs1 or oaep) to encrypt the given
  201. # `ptxfile`, with the (public) RSA key coming from `keyfile` and
  202. # store the cryptogram in `ctxfile`.
  203. ossl_engine_rsa_encrypt () {
  204. local ptxfile=$1
  205. local keyfile=$2
  206. local ctxfile=$3
  207. local padding=$4 # none, pkcs1 or oaep
  208. local hashalg="sha1"
  209. local keyform=${keyfile##*.}
  210. local opt_mgf1_md=""
  211. local opt_digest=""
  212. if [[ "${padding}" == "oaep" ]]; then
  213. :
  214. # opt_mgf1_md="-pkeyopt rsa_mgf1_md:${hashalg}"
  215. # opt_digest="-pkeyopt digest:${hashalg}"
  216. fi
  217. if [ $DO_VALGRIND ]; then
  218. echo "// ossl_engine_rsa_encrypt $2 $3 $4" >> rsa-encrypt-decrypt-sign-verify_$DATESTAMP.log
  219. fi
  220. $VALGRIND ${OSSL} pkeyutl -engine ${engine_id} -encrypt -out ${ctxfile} -in ${ptxfile} \
  221. -inkey ${keyfile} -keyform ${keyform} \
  222. -pkeyopt rsa_padding_mode:${padding} ${opt_mgf1_md} ${opt_digest}
  223. if [ $DO_VALGRIND ]; then
  224. cat $TEMPFILE >> rsa-encrypt-decrypt-sign-verify_$DATESTAMP.log
  225. fi
  226. }
  227. # Use the indicated RSA scheme (none, pkcs1 or oaep) to decrypt the given
  228. # `ctxfile`, with the (private) RSA key coming from `keyfile` and
  229. # store the plain text in `msgfile`.
  230. ossl_rsa_decrypt () {
  231. local ctxfile=$1
  232. local keyfile=$2
  233. local msgfile=$3
  234. local padding=$4 # none, pkcs1 or oaep
  235. local hashalg="sha1"
  236. local keyform=${keyfile##*.}
  237. local opt_mgf1_md=""
  238. local opt_digest=""
  239. if [[ "${padding}" == "oaep" ]]; then
  240. :
  241. # opt_mgf1_md="-pkeyopt rsa_mgf1_md:${hashalg}"
  242. # opt_digest="-pkeyopt digest:${hashalg}"
  243. fi
  244. ${OSSL} pkeyutl -decrypt -out ${msgfile} -in ${ctxfile} \
  245. -inkey ${keyfile} -keyform ${keyform} \
  246. -pkeyopt rsa_padding_mode:${padding} ${opt_mgf1_md} ${opt_digest}
  247. }
  248. # Use the indicated RSA scheme (none, pkcs1 or oaep) to decrypt the given
  249. # `ctxfile`, with the (private) RSA key coming from `keyfile` and
  250. # store the plain text in `msgfile`.
  251. ossl_engine_rsa_decrypt () {
  252. local ctxfile=$1
  253. local keyfile=$2
  254. local msgfile=$3
  255. local padding=$4 # none, pkcs1 or oaep
  256. local hashalg="sha1"
  257. local keyform=${keyfile##*.}
  258. local opt_mgf1_md=""
  259. local opt_digest=""
  260. if [[ "${padding}" == "oaep" ]]; then
  261. :
  262. # opt_mgf1_md="-pkeyopt rsa_mgf1_md:${hashalg}"
  263. # opt_digest="-pkeyopt digest:${hashalg}"
  264. fi
  265. if [ $DO_VALGRIND ]; then
  266. echo "// ossl_engine_rsa_decrypt $2 $3 $4" >> rsa-encrypt-decrypt-sign-verify_$DATESTAMP.log
  267. fi
  268. $VALGRIND ${OSSL} pkeyutl -engine ${engine_id} -decrypt -out ${msgfile} -in ${ctxfile} \
  269. -inkey ${keyfile} -keyform ${keyform} \
  270. -pkeyopt rsa_padding_mode:${padding} ${opt_mgf1_md} ${opt_digest}
  271. if [ $DO_VALGRIND ]; then
  272. cat $TEMPFILE >> rsa-encrypt-decrypt-sign-verify_$DATESTAMP.log
  273. fi
  274. }
  275. # Perform an RSA sign-and-verify test with the specified
  276. # RSA key size and padding/scheme (i.e. pkcs1 or pss).
  277. rsa_sign_and_vrfy_test() {
  278. local nbits=$1
  279. local padding=$2
  280. local keyfile="rsakey_${nbits}.pem"
  281. local msgfile="message.txt"
  282. local sigfile="signature_${padding}_${nbits}"
  283. local verfile="verify_${padding}_${nbits}"
  284. local res="FAILED"
  285. # ossl_gen_rsa_key ${nbits} ${keyfile}
  286. # ossl_show_rsa_key ${keyfile}
  287. echo "My message to sign." > ${msgfile}
  288. # test engine sign
  289. ossl_engine_rsa_sign ${msgfile} ${keyfile} ${sigfile} ${padding}
  290. ossl_rsa_vrfy ${msgfile} ${keyfile} ${sigfile} ${verfile} ${padding}
  291. if grep -q 'Successfully' ${verfile}; then
  292. res="PASSED"
  293. else
  294. res="FAILED"
  295. fi
  296. echo "[INFO] ${engine_id} rsa_sign_test (${nbits}, ${padding}):${res}"
  297. # test engine verify
  298. ossl_rsa_sign ${msgfile} ${keyfile} ${sigfile} ${padding}
  299. ossl_engine_rsa_vrfy ${msgfile} ${keyfile} ${sigfile} ${verfile} ${padding}
  300. if grep -q 'Successfully' ${verfile}; then
  301. res="PASSED"
  302. else
  303. res="FAILED"
  304. fi
  305. echo "[INFO] ${engine_id} rsa_verify_test (${nbits}, ${padding}):${res}"
  306. }
  307. # Perform an RSA encrypt-and-decrypt test with the specified
  308. # RSA key size and padding/scheme (i.e. none, pkcs1 or oaep).
  309. rsa_encrypt_and_decrypt_test() {
  310. local nbits=$1
  311. local padding=$2
  312. local keyfile="rsakey_${nbits}.pem"
  313. local ptxfile="plaintxt"
  314. local ctxfile="ciphertxt_${padding}_${nbits}"
  315. local outfile="plain.out"
  316. local res="FAILED"
  317. echo "My message to encrypt." > ${ptxfile}
  318. if [[ "${padding}" == "none" ]]; then
  319. # Apparently, with padding set to `none`,
  320. # the size of the input must equal the modulus size?!
  321. cp ${ptxfile} ${ptxfile}_${nbits}_none
  322. ptxfile=${ptxfile}_${nbits}_none
  323. padd_file ${ptxfile} $(( ${nbits} / 8 ))
  324. fi
  325. ossl_engine_rsa_encrypt ${ptxfile} ${keyfile} ${ctxfile} ${padding}
  326. ossl_rsa_decrypt ${ctxfile} ${keyfile} ${outfile} ${padding}
  327. /usr/bin/diff --brief ${ptxfile} ${outfile} && res="PASSED"
  328. echo "[INFO] ${engine_id} rsa_encrypt_test (${nbits}, ${padding}): ${res}"
  329. res="FAILED"
  330. ossl_rsa_encrypt ${ptxfile} ${keyfile} ${ctxfile} ${padding}
  331. ossl_engine_rsa_decrypt ${ctxfile} ${keyfile} ${outfile} ${padding}
  332. /usr/bin/diff --brief ${ptxfile} ${outfile} && res="PASSED"
  333. echo "[INFO] ${engine_id} rsa_decrypt_test (${nbits}, ${padding}): ${res}"
  334. }
  335. main () {
  336. ${OSSL} version
  337. if [ "$1" = "-v" ]; then
  338. DO_VALGRIND=1
  339. VALGRIND=$VALGRIND_CMD
  340. echo "// OS_IK rsa-encrypt-decrypt-sign-verify valgrind results - $DATESTAMP" > rsa-encrypt-decrypt-sign-verify_$DATESTAMP.log
  341. fi
  342. echo "**************************"
  343. echo "Generate RSA Keys"
  344. ossl_gen_rsa_key 2048 rsakey_2048.pem
  345. ossl_gen_rsa_key 3072 rsakey_3072.pem
  346. echo "**************************"
  347. echo "Test RSA Sign & Verify"
  348. rsa_sign_and_vrfy_test 2048 pkcs1
  349. rsa_sign_and_vrfy_test 3072 pss
  350. echo "**************************"
  351. echo "Test RSA Encrypt & Decrypt"
  352. rsa_encrypt_and_decrypt_test 3072 none
  353. rsa_encrypt_and_decrypt_test 2048 pkcs1
  354. rsa_encrypt_and_decrypt_test 2048 oaep
  355. if [ $DO_VALGRIND ]; then
  356. rm $TEMPFILE
  357. fi
  358. }
  359. main "$@"