diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 5b875c5..6a9adb0 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -16,14 +16,17 @@ jobs: fail-fast: false matrix: config: - - {os: macOS-latest, r: 'release'} + - {os: windows-latest, r: '3.6'} + - {os: windows-latest, r: '4.1'} + - {os: windows-latest, r: '4.2'} - {os: windows-latest, r: 'release'} - {os: windows-latest, r: 'release', ssl_backend: 'openssl'} - - {os: windows-2022, r: 'devel'} + - {os: windows-latest, r: 'devel'} - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} - {os: ubuntu-latest, r: 'release'} - {os: ubuntu-latest, r: 'oldrel-1'} - + - {os: macOS-latest, r: 'release'} + - {os: flyci-macos-large-latest-m1, r: 'release'} env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} R_KEEP_PKG_SOURCE: yes @@ -33,7 +36,7 @@ jobs: - uses: r-lib/actions/setup-pandoc@v2 - - uses: r-lib/actions/setup-r@v2 + - uses: r-lib/actions/setup-r@m1 with: r-version: ${{ matrix.config.r }} http-user-agent: ${{ matrix.config.http-user-agent }} diff --git a/.github/workflows/rhub.yaml b/.github/workflows/rhub.yaml new file mode 100644 index 0000000..ff3a268 --- /dev/null +++ b/.github/workflows/rhub.yaml @@ -0,0 +1,95 @@ +# R-hub's generic GitHub Actions workflow file. It's canonical location is at +# https://github.com/r-hub/rhub2/blob/v1/inst/workflow/rhub.yaml +# You can update this file to a newer version using the rhub2 package: +# +# rhub2::rhub_setup() +# +# It is unlikely that you need to modify this file manually. + +name: R-hub +run-name: "${{ github.event.inputs.id }}: ${{ github.event.inputs.name || format('Manually run by {0}', github.triggering_actor) }}" + +on: + workflow_dispatch: + inputs: + config: + description: 'A comma separated list of R-hub platforms to use.' + type: string + default: 'linux,windows,macos' + name: + description: 'Run name. You can leave this empty now.' + type: string + id: + description: 'Unique ID. You can leave this empty now.' + type: string + +jobs: + + setup: + runs-on: ubuntu-latest + outputs: + containers: ${{ steps.rhub-setup.outputs.containers }} + platforms: ${{ steps.rhub-setup.outputs.platforms }} + + steps: + # NO NEED TO CHECKOUT HERE + - uses: r-hub/rhub2/actions/rhub-setup@v1 + with: + config: ${{ github.event.inputs.config }} + id: rhub-setup + + linux-containers: + needs: setup + if: ${{ needs.setup.outputs.containers != '[]' }} + runs-on: ubuntu-latest + name: ${{ matrix.config.label }} + strategy: + fail-fast: false + matrix: + config: ${{ fromJson(needs.setup.outputs.containers) }} + container: + image: ${{ matrix.config.container }} + + steps: + - uses: r-hub/rhub2/actions/rhub-checkout@v1 + - uses: r-hub/rhub2/actions/rhub-platform-info@v1 + with: + token: ${{ secrets.RHUB_TOKEN }} + job-config: ${{ matrix.config.job-config }} + - uses: r-hub/rhub2/actions/rhub-setup-deps@v1 + with: + token: ${{ secrets.RHUB_TOKEN }} + job-config: ${{ matrix.config.job-config }} + - uses: r-hub/rhub2/actions/rhub-run-check@v1 + with: + token: ${{ secrets.RHUB_TOKEN }} + job-config: ${{ matrix.config.job-config }} + + other-platforms: + needs: setup + if: ${{ needs.setup.outputs.platforms != '[]' }} + runs-on: ${{ matrix.config.os }} + name: ${{ matrix.config.label }} + strategy: + fail-fast: false + matrix: + config: ${{ fromJson(needs.setup.outputs.platforms) }} + + steps: + - uses: r-hub/rhub2/actions/rhub-checkout@v1 + - uses: r-hub/rhub2/actions/rhub-setup-r@v1 + with: + job-config: ${{ matrix.config.job-config }} + token: ${{ secrets.RHUB_TOKEN }} + - uses: r-hub/rhub2/actions/rhub-platform-info@v1 + with: + token: ${{ secrets.RHUB_TOKEN }} + job-config: ${{ matrix.config.job-config }} + - uses: r-hub/rhub2/actions/rhub-setup-deps@v1 + with: + job-config: ${{ matrix.config.job-config }} + token: ${{ secrets.RHUB_TOKEN }} + - uses: r-hub/rhub2/actions/rhub-run-check@v1 + with: + job-config: ${{ matrix.config.job-config }} + token: ${{ secrets.RHUB_TOKEN }} diff --git a/DESCRIPTION b/DESCRIPTION index f5f8652..81722f4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: openssl Type: Package Title: Toolkit for Encryption, Signatures and Certificates Based on OpenSSL -Version: 2.0.6 +Version: 2.1.1 Authors@R: c(person("Jeroen", "Ooms", role = c("aut", "cre"), email = "jeroen@berkeley.edu", comment = c(ORCID = "0000-0002-4035-0289")), person("Oliver", "Keyes", role = "ctb")) @@ -15,7 +15,7 @@ Description: Bindings to OpenSSL libssl and libcrypto, plus custom SSH key parse number generator, and 'bignum' math methods for manually performing crypto calculations on large multibyte integers. License: MIT + file LICENSE -URL: https://github.com/jeroen/openssl +URL: https://jeroen.r-universe.dev/openssl BugReports: https://github.com/jeroen/openssl/issues SystemRequirements: OpenSSL >= 1.0.2 VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index 71ec2f5..c88e843 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -118,6 +118,7 @@ export(sha1) export(sha2) export(sha224) export(sha256) +export(sha3) export(sha384) export(sha512) export(signature_create) diff --git a/NEWS b/NEWS index 4f12094..704a8be 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,10 @@ +2.1.1 + - Windows: update to openssl 3.1.2 + arm support + 2.1.0 - - MacOS and Windows binaries have been bumped to libssl 3.1.0 + - Windows and autobrew binaries have been bumped to libssl 3.1.1. (MacOS CRAN + binaries use libssl from CRAN 'recipes' which is currently libssl 1.1.1) + - Added sha3() function 2.0.6 - Add new functions pkcs7_encrypt and pkcs7_decrypt diff --git a/R/hash.R b/R/hash.R index f489b1a..6933b97 100644 --- a/R/hash.R +++ b/R/hash.R @@ -103,6 +103,12 @@ sha2 <- function(x, size = 256, key = NULL){ rawstringhash(x, paste0("sha", size), key) } +#' @rdname hash +#' @export +sha3 <- function(x, size = 256, key = NULL){ + rawstringhash(x, paste0("sha3-", size), key) +} + #' @rdname hash #' @export md4 <- function(x, key = NULL){ diff --git a/R/openssh.R b/R/openssh.R index f9ad6d7..d1fa06c 100644 --- a/R/openssh.R +++ b/R/openssh.R @@ -35,7 +35,7 @@ fingerprint.pubkey <- function(key, hashfun = sha256){ hashfun(unlist(unname(hashdata))) } -fpdata <- function(x, ...){ +fpdata <- function(pubkey){ UseMethod("fpdata") } diff --git a/R/rsa.R b/R/rsa.R index 404abd1..a038e22 100644 --- a/R/rsa.R +++ b/R/rsa.R @@ -8,6 +8,7 @@ #' #' @export #' @param data raw vector of max 245 bytes (for 2048 bit keys) with data to encrypt/decrypt +#' @param oaep if TRUE, changes padding to EME-OAEP as defined in PKCS #1 v2.0 #' @inheritParams signature_create #' @rdname rsa_encrypt #' @aliases rsa encrypt @@ -28,19 +29,21 @@ #' tempkey <- rsa_decrypt(ciphertext, key) #' message <- aes_cbc_decrypt(blob, tempkey, iv) #' out <- rawToChar(message) -rsa_encrypt <- function(data, pubkey = my_pubkey()){ +rsa_encrypt <- function(data, pubkey = my_pubkey(), oaep = FALSE){ pk <- read_pubkey(pubkey) stopifnot(inherits(pk, "rsa")) stopifnot(is.raw(data)) - .Call(R_rsa_encrypt, data, pk) + oaep <- as.logical(oaep) + .Call(R_rsa_encrypt, data, pk, oaep) } #' @useDynLib openssl R_rsa_decrypt #' @export #' @rdname rsa_encrypt -rsa_decrypt <- function(data, key = my_key(), password = askpass){ +rsa_decrypt <- function(data, key = my_key(), password = askpass, oaep = FALSE){ sk <- read_key(key, password) stopifnot(inherits(sk, "rsa")) stopifnot(is.raw(data)) - .Call(R_rsa_decrypt, data, sk) + oaep <- as.logical(oaep) + .Call(R_rsa_decrypt, data, sk, oaep) } diff --git a/configure b/configure index 362d8a9..92bfcff 100755 --- a/configure +++ b/configure @@ -37,8 +37,8 @@ elif [ `uname` = "Darwin" ]; then test ! "$CI" && brew --version 2>/dev/null if [ $? -eq 0 ]; then BREWDIR=`brew --prefix` - PKG_CFLAGS="-I$BREWDIR/opt/openssl/include -I$BREWDIR/opt/openssl@1.1/include" - PKG_LIBS="-L$BREWDIR/opt/openssl/lib -L$BREWDIR/opt/openssl@1.1/lib $PKG_LIBS" + PKG_CFLAGS="-I$BREWDIR/opt/openssl/include" + PKG_LIBS="-L$BREWDIR/opt/openssl/lib $PKG_LIBS" else curl -sfL "https://autobrew.github.io/scripts/$PKG_BREW_NAME" > autobrew . ./autobrew @@ -76,7 +76,7 @@ fi # Try to link against the correct OpenSSL version if [ -z "$AUTOBREW" ]; then -SONAME=`${CC} -E ${PKG_CFLAGS} src/tests/soname.h | sh | xargs` +SONAME=`${CC} -E ${PKG_CFLAGS} src/tests/soname.h | grep 'echo' | sh | xargs` if [ "$SONAME" ]; then if [ `uname` = "Darwin" ]; then PKG_LIBS_VERSIONED=`echo "${PKG_LIBS}" | sed "s/-lssl/-lssl.${SONAME}/" | sed "s/-lcrypto/-lcrypto.${SONAME}/"` diff --git a/man/hash.Rd b/man/hash.Rd index 4c2c736..eca87e6 100644 --- a/man/hash.Rd +++ b/man/hash.Rd @@ -11,6 +11,7 @@ \alias{sha384} \alias{sha512} \alias{sha2} +\alias{sha3} \alias{md4} \alias{md5} \alias{blake2b} @@ -31,6 +32,8 @@ sha512(x, key = NULL) sha2(x, size = 256, key = NULL) +sha3(x, size = 256, key = NULL) + md4(x, key = NULL) md5(x, key = NULL) diff --git a/man/rsa_encrypt.Rd b/man/rsa_encrypt.Rd index 4127f02..ba1413f 100644 --- a/man/rsa_encrypt.Rd +++ b/man/rsa_encrypt.Rd @@ -7,15 +7,17 @@ \alias{rsa_decrypt} \title{Low-level RSA encryption} \usage{ -rsa_encrypt(data, pubkey = my_pubkey()) +rsa_encrypt(data, pubkey = my_pubkey(), oaep = FALSE) -rsa_decrypt(data, key = my_key(), password = askpass) +rsa_decrypt(data, key = my_key(), password = askpass, oaep = FALSE) } \arguments{ \item{data}{raw vector of max 245 bytes (for 2048 bit keys) with data to encrypt/decrypt} \item{pubkey}{public key or file path. See \code{\link[=read_pubkey]{read_pubkey()}}.} +\item{oaep}{if TRUE, changes padding to EME-OAEP as defined in PKCS #1 v2.0} + \item{key}{private key or file path. See \code{\link[=read_key]{read_key()}}.} \item{password}{string or a function to read protected keys. See \code{\link[=read_key]{read_key()}}.} diff --git a/src/Makevars.ucrt b/src/Makevars.ucrt deleted file mode 100644 index 1a2e101..0000000 --- a/src/Makevars.ucrt +++ /dev/null @@ -1,2 +0,0 @@ -CRT=-ucrt -include Makevars.win diff --git a/src/Makevars.win b/src/Makevars.win index a17fb08..a98f3fe 100644 --- a/src/Makevars.win +++ b/src/Makevars.win @@ -1,10 +1,16 @@ -VERSION = 1.1.1k -PKG_CPPFLAGS = -I../windows/openssl-$(VERSION)/include -PKG_LIBS = -Lbcrypt -lstatbcrypt -L../windows/openssl-$(VERSION)/lib${R_ARCH}${CRT} \ - -lssl -lcrypto -lws2_32 -lgdi32 -lcrypt32 +RWINLIB = ../windows/libssl +TARGET = lib$(subst gcc,,$(COMPILED_BY))$(R_ARCH) +PKG_CPPFLAGS = -I$(RWINLIB)/include -DOPENSSL_SUPPRESS_DEPRECATED + STATLIB = bcrypt/libstatbcrypt.a LIBBCRYPT = bcrypt/bcrypt_pbkdf.o bcrypt/blowfish.o +PKG_LIBS = \ + -Lbcrypt -lstatbcrypt \ + -L$(RWINLIB)/$(TARGET) \ + -L$(RWINLIB)/lib \ + -lssl -lcrypto -lz -lws2_32 -lgdi32 -lcrypt32 + #all: clean all: $(SHLIB) @@ -15,7 +21,7 @@ $(SHLIB): $(OBJECTS) $(STATLIB) $(STATLIB): $(LIBBCRYPT) winlibs: - "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" "../tools/winlibs.R" $(VERSION) + "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" "../tools/winlibs.R" clean: rm -f $(SHLIB) $(OBJECTS) $(STATLIB) $(LIBBCRYPT) diff --git a/src/rsa.c b/src/rsa.c index 512d354..38a23b4 100644 --- a/src/rsa.c +++ b/src/rsa.c @@ -5,13 +5,14 @@ #include #include "utils.h" -SEXP R_rsa_encrypt(SEXP data, SEXP keydata) { +SEXP R_rsa_encrypt(SEXP data, SEXP keydata, SEXP oaep) { const unsigned char *ptr = RAW(keydata); RSA *rsa = d2i_RSA_PUBKEY(NULL, &ptr, LENGTH(keydata)); + int pad = asLogical(oaep) ? RSA_PKCS1_OAEP_PADDING : RSA_PKCS1_PADDING; bail(!!rsa); int keysize = RSA_size(rsa); unsigned char* buf = OPENSSL_malloc(keysize); - int len = RSA_public_encrypt(LENGTH(data), RAW(data), buf, rsa, RSA_PKCS1_PADDING); + int len = RSA_public_encrypt(LENGTH(data), RAW(data), buf, rsa, pad); bail(len > 0); RSA_free(rsa); SEXP res = allocVector(RAWSXP, len); @@ -20,13 +21,14 @@ SEXP R_rsa_encrypt(SEXP data, SEXP keydata) { return res; } -SEXP R_rsa_decrypt(SEXP data, SEXP keydata){ +SEXP R_rsa_decrypt(SEXP data, SEXP keydata, SEXP oaep){ const unsigned char *ptr = RAW(keydata); RSA *rsa = d2i_RSAPrivateKey(NULL, &ptr, LENGTH(keydata)); + int pad = asLogical(oaep) ? RSA_PKCS1_OAEP_PADDING : RSA_PKCS1_PADDING; bail(!!rsa); int keysize = RSA_size(rsa); unsigned char* buf = OPENSSL_malloc(keysize); - int len = RSA_private_decrypt(LENGTH(data), RAW(data), buf, rsa, RSA_PKCS1_PADDING); + int len = RSA_private_decrypt(LENGTH(data), RAW(data), buf, rsa, pad); bail(len > 0); RSA_free(rsa); SEXP res = allocVector(RAWSXP, len); diff --git a/tests/testthat/test_sodium.R b/tests/testthat/test_sodium.R index 804ac0e..3a46200 100644 --- a/tests/testthat/test_sodium.R +++ b/tests/testthat/test_sodium.R @@ -1,6 +1,7 @@ context("Sodium Compatibility") test_that("Signatures are compatible with sodium", { + skip_if_not_installed('sodium') skip_if(fips_mode()) skip_if_not(openssl_config()$x25519) @@ -26,6 +27,7 @@ test_that("Signatures are compatible with sodium", { }) test_that("Diffie Hellman is compatible with sodium", { + skip_if_not_installed('sodium') skip_if(fips_mode()) skip_if_not(openssl_config()$x25519) # Generate keypair with sodium diff --git a/tests/testthat/test_ssl_ctx.R b/tests/testthat/test_ssl_ctx.R index 5ad219a..1c49778 100644 --- a/tests/testthat/test_ssl_ctx.R +++ b/tests/testthat/test_ssl_ctx.R @@ -2,6 +2,7 @@ test_that("ssl-ctx integration works", { skip_if_not_installed('curl') skip_if(packageVersion('curl') < '4.3.3') skip_if_not(ssl_ctx_curl_version_match()) + skip_if_offline() test <- download_ssl_cert('cran.r-project.org')[[1]] diff --git a/tools/winlibs.R b/tools/winlibs.R index 4b0597e..68f75d8 100644 --- a/tools/winlibs.R +++ b/tools/winlibs.R @@ -1,10 +1,18 @@ -# Build against mingw-w64 build of openssl -VERSION <- commandArgs(TRUE) -if(!file.exists(sprintf("../windows/openssl-%s/include/openssl/ssl.h", VERSION))){ - if(getRversion() < "3.3.0") setInternet2() - download.file(sprintf("https://github.com/rwinlib/openssl/archive/v%s.zip", VERSION), - "lib.zip", quiet = TRUE) +if(!file.exists("../windows/libssl/include/openssl/pem.h")){ + unlink("../windows", recursive = TRUE) + url <- if(grepl("aarch", R.version$platform)){ + "https://github.com/r-windows/bundles/releases/download/openssl-3.1.2/openssl-3.1.2-clang-aarch64.tar.xz" + } else if(grepl("clang", Sys.getenv('R_COMPILED_BY'))){ + "https://github.com/r-windows/bundles/releases/download/openssl-3.1.2/openssl-3.1.2-clang-x86_64.tar.xz" + } else if(getRversion() >= "4.2") { + "https://github.com/r-windows/bundles/releases/download/openssl-3.1.2/openssl-3.1.2-ucrt-x86_64.tar.xz" + } else { + "https://github.com/rwinlib/openssl/archive/v3.1.1.tar.gz" + } + download.file(url, basename(url), quiet = TRUE) dir.create("../windows", showWarnings = FALSE) - unzip("lib.zip", exdir = "../windows") - unlink("lib.zip") + untar(basename(url), exdir = "../windows", tar = 'internal') + unlink(basename(url)) + setwd("../windows") + file.rename(list.files(), 'libssl') }