Jelajahi Sumber

Merge pull request #584 from libtom/cleanup

Clean-up & minor improvements
Steffen Jaeckel 3 tahun lalu
induk
melakukan
06a81aeb22
44 mengubah file dengan 464 tambahan dan 327 penghapusan
  1. 3 3
      .ci/coverage.sh
  2. 67 0
      .github/workflows/main.yml
  3. 0 111
      .travis.yml
  4. 25 25
      doc/crypt.tex
  5. 1 1
      makefile_include.mk
  6. 1 1
      src/encauth/gcm/gcm_add_aad.c
  7. 7 7
      src/headers/tomcrypt_custom.h
  8. 1 0
      src/headers/tomcrypt_misc.h
  9. 18 6
      src/headers/tomcrypt_private.h
  10. 55 10
      src/misc/base64/base64_encode.c
  11. 6 0
      src/misc/padding/padding_depad.c
  12. 9 2
      src/misc/padding/padding_pad.c
  13. 4 0
      src/pk/asn1/der/short_integer/der_decode_short_integer.c
  14. 6 6
      src/pk/asn1/oid/pk_get_oid.c
  15. 2 1
      src/pk/asn1/oid/pk_oid_str.c
  16. 1 1
      src/pk/asn1/x509/x509_decode_public_key_from_certificate.c
  17. 1 1
      src/pk/dsa/dsa_export.c
  18. 1 1
      src/pk/dsa/dsa_import.c
  19. 37 36
      src/pk/ecc/ecc_export_openssl.c
  20. 1 1
      src/pk/ecc/ecc_import_pkcs8.c
  21. 3 3
      src/pk/ecc/ecc_import_x509.c
  22. 1 1
      src/pk/ecc/ecc_ssh_ecdsa_encode_name.c
  23. 1 1
      src/pk/ed25519/ed25519_export.c
  24. 2 2
      src/pk/ed25519/ed25519_import.c
  25. 1 1
      src/pk/ed25519/ed25519_import_pkcs8.c
  26. 1 1
      src/pk/ed25519/ed25519_import_raw.c
  27. 2 2
      src/pk/ed25519/ed25519_import_x509.c
  28. 1 1
      src/pk/ed25519/ed25519_make_key.c
  29. 1 1
      src/pk/ed25519/ed25519_sign.c
  30. 1 1
      src/pk/ed25519/ed25519_verify.c
  31. 1 1
      src/pk/rsa/rsa_export.c
  32. 70 46
      src/pk/rsa/rsa_import.c
  33. 9 22
      src/pk/rsa/rsa_import_pkcs8.c
  34. 1 1
      src/pk/rsa/rsa_import_x509.c
  35. 1 1
      src/pk/x25519/x25519_export.c
  36. 2 2
      src/pk/x25519/x25519_import.c
  37. 1 1
      src/pk/x25519/x25519_import_pkcs8.c
  38. 1 1
      src/pk/x25519/x25519_import_raw.c
  39. 2 2
      src/pk/x25519/x25519_import_x509.c
  40. 1 1
      src/pk/x25519/x25519_make_key.c
  41. 24 3
      tests/base64_test.c
  42. 2 1
      tests/common.c
  43. 70 18
      tests/der_test.c
  44. 19 0
      tests/padding_test.c

+ 3 - 3
.ci/coverage.sh

@@ -37,11 +37,11 @@ fi
 bash .ci/coverage_more.sh "$5" > test_coverage_more.txt || { rm -f testok.txt && exit 1 ; }
 
 make lcov-single
-# if this isn't run on Travis CI create coverage locally
-if [ "$TRAVIS" == "" ]; then
+# if this isn't run on CI create coverage locally
+if [ "$CI" == "" ]; then
    make lcov-html
 else
-   coveralls-lcov coverage.info
+   coveralls-lcov coverage.info --service-job-id="$GITHUB_RUN_ID" --service-name="github" --repo-token="$REPO_TOKEN" --branch="$GITHUB_REF_NAME" --service-pull-request="$PR_NUMBER"
 fi
 
 exit 0

+ 67 - 0
.github/workflows/main.yml

@@ -0,0 +1,67 @@
+name: CI
+
+on:
+  push:
+    branches:
+      - master
+      - develop
+      - /^release\/.*$/
+  pull_request:
+    branches:
+      - master
+      - develop
+      - /^release\/.*$/
+
+jobs:
+  Build:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        cc: [ gcc, clang ]
+        os: [ ubuntu-18.04 ]
+        config:
+          - { BUILDNAME: 'META_BUILDS',          BUILDOPTIONS: '-DGMP_DESC',                                          BUILDSCRIPT: '.ci/meta_builds.sh' }
+          - { BUILDNAME: 'VALGRIND',             BUILDOPTIONS: '',                                                    BUILDSCRIPT: '.ci/valgrind.sh' }
+          - { BUILDNAME: 'STOCK',                BUILDOPTIONS: '',                                                    BUILDSCRIPT: '.ci/run.sh' }
+          - { BUILDNAME: 'STOCK-MPI',            BUILDOPTIONS: '-ULTM_DESC -UTFM_DESC -UUSE_LTM -UUSE_TFM',           BUILDSCRIPT: '.ci/run.sh' }
+          - { BUILDNAME: 'EASY',                 BUILDOPTIONS: '-DLTC_EASY',                                          BUILDSCRIPT: '.ci/run.sh' }
+          - { BUILDNAME: 'SMALL',                BUILDOPTIONS: '-DLTC_SMALL_CODE',                                    BUILDSCRIPT: '.ci/run.sh' }
+          - { BUILDNAME: 'NOTABLES',             BUILDOPTIONS: '-DLTC_NO_TABLES',                                     BUILDSCRIPT: '.ci/run.sh' }
+          - { BUILDNAME: 'SMALL+NOTABLES',       BUILDOPTIONS: '-DLTC_SMALL_CODE -DLTC_NO_TABLES',                    BUILDSCRIPT: '.ci/run.sh' }
+          - { BUILDNAME: 'NO_FAST',              BUILDOPTIONS: '-DLTC_NO_FAST',                                       BUILDSCRIPT: '.ci/run.sh' }
+          - { BUILDNAME: 'NO_FAST+NOTABLES',     BUILDOPTIONS: '-DLTC_NO_FAST -DLTC_NO_TABLES',                       BUILDSCRIPT: '.ci/run.sh' }
+          - { BUILDNAME: 'NO_ASM',               BUILDOPTIONS: '-DLTC_NO_ASM',                                        BUILDSCRIPT: '.ci/run.sh' }
+          - { BUILDNAME: 'NO_TIMING_RESISTANCE', BUILDOPTIONS: '-DLTC_NO_ECC_TIMING_RESISTANT -DLTC_NO_RSA_BLINDING', BUILDSCRIPT: '.ci/run.sh' }
+          - { BUILDNAME: 'PTHREAD',              BUILDOPTIONS: '-DLTC_PTHREAD',                                       BUILDSCRIPT: '.ci/run.sh' }
+          - { BUILDNAME: 'STOCK+ARGTYPE=1',      BUILDOPTIONS: '-DARGTYPE=1',                                         BUILDSCRIPT: '.ci/run.sh' }
+          - { BUILDNAME: 'STOCK+ARGTYPE=2',      BUILDOPTIONS: '-DARGTYPE=2',                                         BUILDSCRIPT: '.ci/run.sh' }
+          - { BUILDNAME: 'STOCK+ARGTYPE=3',      BUILDOPTIONS: '-DARGTYPE=3',                                         BUILDSCRIPT: '.ci/run.sh' }
+          - { BUILDNAME: 'STOCK+ARGTYPE=4',      BUILDOPTIONS: '-DARGTYPE=4',                                         BUILDSCRIPT: '.ci/run.sh' }
+    steps:
+      - uses: actions/checkout@v2
+      - name: install dependencies
+        run: |
+          sudo apt-get update -qq
+          sudo apt-get install -y libtommath-dev libgmp-dev libtfm-dev valgrind libtool-bin clang-tools lcov
+          sudo gem install coveralls-lcov
+          curl -s https://packagecloud.io/install/repositories/libtom/packages/script.deb.sh | sudo bash
+          sudo apt-get install libtfm1=0.13-5ubuntu1
+      - name: run tests
+        env:
+          CC: "${{ matrix.cc }}"
+          PR_NUMBER: ${{ github.event.number }}
+          REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        run: |
+          bash "${{ matrix.config.BUILDSCRIPT }}" "${{ matrix.config.BUILDNAME }}" "-DUSE_LTM -DLTM_DESC" "makefile V=1"        "${{ matrix.config.BUILDOPTIONS }}" "-ltommath"
+          bash "${{ matrix.config.BUILDSCRIPT }}" "${{ matrix.config.BUILDNAME }}" "-DUSE_TFM -DTFM_DESC" "makefile.shared V=1" "${{ matrix.config.BUILDOPTIONS }}" "-ltfm"
+      - name: regular logs
+        if: ${{ !failure() }}
+        run: |
+          cat gcc_1.txt
+          cat gcc_2.txt
+      - name: error logs
+        if: ${{ failure() }}
+        run: |
+          cat test_std.txt
+          cat test_err.txt
+          cat tv.txt

+ 0 - 111
.travis.yml

@@ -1,111 +0,0 @@
-dist: bionic
-sudo: required
-
-language: c
-
-before_install:
-    - sudo apt-get update -qq
-    - sudo apt-get install -y libtommath-dev libgmp-dev libtfm-dev valgrind libtool-bin
-
-before_script:
-  - gem install coveralls-lcov
-  - curl http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz | tar xz
-  - export PATH=$PATH:`pwd`/lcov-1.11/bin
-  - curl -s https://packagecloud.io/install/repositories/libtom/packages/script.deb.sh | sudo bash
-  - sudo apt-get install libtfm1=0.13-5ubuntu1
-
-matrix:
-  fast_finish: true
-branches:
-  only:
-    - master
-    - develop
-    - /^release\/.*$/
-
-compiler:
-  - gcc
-  - clang
-script:
-  - bash "${BUILDSCRIPT}" "${BUILDNAME}" "-DUSE_LTM -DLTM_DESC" "makefile V=1"        "${BUILDOPTIONS}" "-ltommath" &&
-    bash "${BUILDSCRIPT}" "${BUILDNAME}" "-DUSE_TFM -DTFM_DESC" "makefile.shared V=1" "${BUILDOPTIONS}" "-ltfm"
-env:
-  - |
-    BUILDNAME="META_BUILDS"
-    BUILDOPTIONS="-DGMP_DESC"
-    BUILDSCRIPT=".ci/meta_builds.sh"
-  - |
-    BUILDNAME="VALGRIND"
-    BUILDOPTIONS=" "
-    BUILDSCRIPT=".ci/valgrind.sh"
-  - |
-    BUILDNAME="STOCK"
-    BUILDOPTIONS=" "
-    BUILDSCRIPT=".ci/run.sh"
-  - |
-    BUILDNAME="STOCK-MPI"
-    BUILDOPTIONS="-ULTM_DESC -UTFM_DESC -UUSE_LTM -UUSE_TFM"
-    BUILDSCRIPT=".ci/run.sh"
-  - |
-    BUILDNAME="EASY"
-    BUILDOPTIONS="-DLTC_EASY"
-    BUILDSCRIPT=".ci/run.sh"
-  - |
-    BUILDNAME="SMALL"
-    BUILDOPTIONS="-DLTC_SMALL_CODE"
-    BUILDSCRIPT=".ci/run.sh"
-  - |
-    BUILDNAME="NOTABLES"
-    BUILDOPTIONS="-DLTC_NO_TABLES"
-    BUILDSCRIPT=".ci/run.sh"
-  - |
-    BUILDNAME="SMALL+NOTABLES"
-    BUILDOPTIONS="-DLTC_SMALL_CODE -DLTC_NO_TABLES"
-    BUILDSCRIPT=".ci/run.sh"
-  - |
-    BUILDNAME="NO_FAST"
-    BUILDOPTIONS="-DLTC_NO_FAST"
-    BUILDSCRIPT=".ci/run.sh"
-  - |
-    BUILDNAME="NO_FAST+NOTABLES"
-    BUILDOPTIONS="-DLTC_NO_FAST -DLTC_NO_TABLES"
-    BUILDSCRIPT=".ci/run.sh"
-  - |
-    BUILDNAME="NO_ASM"
-    BUILDOPTIONS="-DLTC_NO_ASM"
-    BUILDSCRIPT=".ci/run.sh"
-  - |
-    BUILDNAME="NO_TIMING_RESISTANCE"
-    BUILDOPTIONS="-DLTC_NO_ECC_TIMING_RESISTANT -DLTC_NO_RSA_BLINDING"
-    BUILDSCRIPT=".ci/run.sh"
-  - |
-    BUILDNAME="PTHREAD"
-    BUILDOPTIONS="-DLTC_PTHREAD"
-    BUILDSCRIPT=".ci/run.sh"
-  - |
-    BUILDNAME="STOCK+ARGTYPE=1"
-    BUILDOPTIONS="-DARGTYPE=1"
-    BUILDSCRIPT=".ci/run.sh"
-  - |
-    BUILDNAME="STOCK+ARGTYPE=2"
-    BUILDOPTIONS="-DARGTYPE=2"
-    BUILDSCRIPT=".ci/run.sh"
-  - |
-    BUILDNAME="STOCK+ARGTYPE=3"
-    BUILDOPTIONS="-DARGTYPE=3"
-    BUILDSCRIPT=".ci/run.sh"
-  - |
-    BUILDNAME="STOCK+ARGTYPE=4"
-    BUILDOPTIONS="-DARGTYPE=4"
-    BUILDSCRIPT=".ci/run.sh"
-
-after_failure:
-  - cat test_std.txt
-  - cat test_err.txt
-  - cat tv.txt
-
-after_script:
-  - cat gcc_1.txt
-  - cat gcc_2.txt
-
-notifications:
-  irc: "chat.freenode.net#libtom-notifications"

+ 25 - 25
doc/crypt.tex

@@ -604,30 +604,30 @@ As of this release the current cipher\_descriptors elements are the following:
 \begin{figure}[hpbt]
 \begin{small}
 \begin{center}
-\begin{tabular}{|c|c|c|c|c|c|}
-     \hline \textbf{Name} & \textbf{Descriptor Name} & \textbf{Block Size} & \textbf{Key Range} & \textbf{Rounds} \\
-     \hline Blowfish & blowfish\_desc & 8 & 8 $\ldots$ 56 & 16 \\
-     \hline X-Tea & xtea\_desc & 8 & 16 & 32 \\
-     \hline RC2 & rc2\_desc & 8 & 5 $\ldots$ 128 & 16 \\
-     \hline RC5-32/12/b & rc5\_desc & 8 & 8 $\ldots$ 128 & 12 $\ldots$ 24 \\
-     \hline RC6-32/20/b & rc6\_desc & 16 & 8 $\ldots$ 128 & 20 \\
-     \hline SAFER+ & saferp\_desc &16 & 16, 24, 32 & 8, 12, 16 \\
-     \hline AES & aes\_desc & 16 & 16, 24, 32 & 10, 12, 14 \\
-                & aes\_enc\_desc & 16 & 16, 24, 32 & 10, 12, 14 \\
-     \hline Twofish & twofish\_desc & 16 & 16, 24, 32 & 16 \\
-     \hline DES & des\_desc & 8 & 8 & 16 \\
-     \hline 3DES (EDE mode) & des3\_desc & 8 & 16, 24 & 16 \\
-     \hline CAST5 (CAST-128) & cast5\_desc & 8 & 5 $\ldots$ 16 & 12, 16 \\
-     \hline Noekeon & noekeon\_desc & 16 & 16 & 16 \\
-     \hline Skipjack & skipjack\_desc & 8 & 10 & 32 \\
-     \hline Anubis & anubis\_desc & 16 & 16 $\ldots$ 40 & 12 $\ldots$ 18 \\
-     \hline Khazad & khazad\_desc & 8 & 16 & 8 \\
-     \hline SEED   & kseed\_desc & 16 & 16 & 16 \\
-     \hline KASUMI & kasumi\_desc & 8 & 16 & 8 \\
-     \hline Camellia & camellia\_desc & 16 & 16, 24, 32 & 18, 24 \\
-     \hline IDEA & idea\_desc & 8 & 16 & 8 \\
-     \hline Serpent & serpent\_desc & 16 & 16, 24, 32 & 32 \\
-     \hline TEA & tea\_desc & 8 & 16 & 32 \\
+\begin{tabular}{|c|c|c|c|c|c|c|}
+     \hline \textbf{Name} & \textbf{Descriptor Name} & \textbf{Block Size} & \textbf{Key Range} & \textbf{Rounds} & \textbf{Id} \\
+     \hline Blowfish & blowfish\_desc & 8 & 8 $\ldots$ 56 & 16 & 0 \\
+     \hline X-Tea & xtea\_desc & 8 & 16 & 32 & 1 \\
+     \hline RC2 & rc2\_desc & 8 & 5 $\ldots$ 128 & 16 & 12 \\
+     \hline RC5-32/12/b & rc5\_desc & 8 & 8 $\ldots$ 128 & 12 $\ldots$ 24 & 2 \\
+     \hline RC6-32/20/b & rc6\_desc & 16 & 8 $\ldots$ 128 & 20 & 3 \\
+     \hline SAFER+ & saferp\_desc &16 & 16, 24, 32 & 8, 12, 16 & 4 \\
+     \hline AES & aes\_desc & 16 & 16, 24, 32 & 10, 12, 14 & 6 \\
+                & aes\_enc\_desc & 16 & 16, 24, 32 & 10, 12, 14 & 6 \\
+     \hline Twofish & twofish\_desc & 16 & 16, 24, 32 & 16 & 7 \\
+     \hline DES & des\_desc & 8 & 8 & 16 & 13 \\
+     \hline 3DES (EDE mode) & des3\_desc & 8 & 16, 24 & 16 & 14 \\
+     \hline CAST5 (CAST-128) & cast5\_desc & 8 & 5 $\ldots$ 16 & 12, 16 & 15 \\
+     \hline Noekeon & noekeon\_desc & 16 & 16 & 16 & 16 \\
+     \hline Skipjack & skipjack\_desc & 8 & 10 & 32 & 17 \\
+     \hline Anubis & anubis\_desc & 16 & 16 $\ldots$ 40 & 12 $\ldots$ 18 & 19 \\
+     \hline Khazad & khazad\_desc & 8 & 16 & 8 & 18 \\
+     \hline SEED   & kseed\_desc & 16 & 16 & 16 & 20 \\
+     \hline KASUMI & kasumi\_desc & 8 & 16 & 8 & 21 \\
+     \hline Camellia & camellia\_desc & 16 & 16, 24, 32 & 18, 24 & 23 \\
+     \hline IDEA & idea\_desc & 8 & 16 & 8 & 24 \\
+     \hline Serpent & serpent\_desc & 16 & 16, 24, 32 & 32 & 25 \\
+     \hline TEA & tea\_desc & 8 & 16 & 32 & 26 \\
      \hline
 \end{tabular}
 \end{center}
@@ -1546,7 +1546,7 @@ At the end you have to terminate the state:
 err = rc4_stream_done(&st);
 \end{verbatim}
 
-To encrypt plaintext (or decrypt ciphertext) using RC6 for data already in
+To encrypt plaintext (or decrypt ciphertext) using RC4 for data already in
 memory with a single function call, the following function may be used.
 \begin{verbatim}
 err = rc4_stream_memory(key, keylen, datain, datalen, dataout);

+ 1 - 1
makefile_include.mk

@@ -120,7 +120,7 @@ endif # LTC_SMALL
 
 ifneq ($(findstring clang,$(CC)),)
 LTC_CFLAGS += -Wno-typedef-redefinition -Wno-tautological-compare -Wno-builtin-requires-header
-LTC_CFLAGS += -Wno-missing-field-initializers -Wno-missing-braces
+LTC_CFLAGS += -Wno-missing-field-initializers -Wno-missing-braces -Wno-incomplete-setjmp-declaration
 endif
 ifneq ($(findstring mingw,$(CC)),)
 LTC_CFLAGS += -Wno-shadow -Wno-attributes

+ 1 - 1
src/encauth/gcm/gcm_add_aad.c

@@ -83,7 +83,7 @@ int gcm_add_aad(gcm_state *gcm,
 
    x = 0;
 #ifdef LTC_FAST
-   if (gcm->buflen == 0) {
+   if (gcm->buflen == 0 && adatalen > 15) {
       for (x = 0; x < (adatalen & ~15); x += 16) {
           for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
               *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&adata[x + y]));

+ 7 - 7
src/headers/tomcrypt_custom.h

@@ -114,7 +114,7 @@
 
    #define LTC_NO_MISC
    #define LTC_BASE64
-#endif
+#endif /* LTC_EASY */
 
 /* The minimal set of functionality to run the tests */
 #ifdef LTC_MINIMAL
@@ -129,7 +129,7 @@
    #define LTC_TRY_URANDOM_FIRST
 
    #undef LTC_NO_FILE
-#endif
+#endif /* LTC_MINIMAL */
 
 /* Enable self-test test vector checking */
 #ifndef LTC_NO_TEST
@@ -357,7 +357,7 @@
   #define LTC_YARROW_AES 2
 #endif
 
-#endif
+#endif /* LTC_YARROW */
 
 #ifdef LTC_FORTUNA
 
@@ -553,7 +553,7 @@
    #define LTC_ECC_SECP384R1
    #define LTC_ECC_SECP521R1
 #endif
-#endif
+#endif /* LTC_MECC */
 
 #if defined(LTC_DER)
    #ifndef LTC_DER_MAX_RECURSION
@@ -690,15 +690,13 @@
 #define LTC_MUTEX_UNLOCK(x)
 #define LTC_MUTEX_DESTROY(x)
 
-#endif
+#endif /* LTC_PTHREAD */
 
 /* Debuggers */
 
 /* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and RC4 work (see the code) */
 /* #define LTC_VALGRIND */
 
-#endif
-
 #ifndef LTC_NO_FILE
    /* buffer size for reading from a file via fread(..) */
    #ifndef LTC_FILE_READ_BUFSIZE
@@ -739,3 +737,5 @@
 #define LTC_ECC_SECP521R1
 #undef LTC_ECC521
 #endif
+
+#endif /* TOMCRYPT_CUSTOM_H_ */

+ 1 - 0
src/headers/tomcrypt_misc.h

@@ -146,6 +146,7 @@ enum padding_type {
    LTC_PAD_ISO_10126    = 0x1000U,
 #endif
    LTC_PAD_ANSI_X923    = 0x2000U,
+   LTC_PAD_SSH          = 0x3000U,
    /* The following padding modes don't contain the padding
     * length as last byte of the padding.
     */

+ 18 - 6
src/headers/tomcrypt_private.h

@@ -14,12 +14,12 @@
  */
 
 enum ltc_oid_id {
-   PKA_RSA,
-   PKA_DSA,
-   PKA_EC,
-   PKA_EC_PRIMEF,
-   PKA_X25519,
-   PKA_ED25519,
+   LTC_OID_RSA,
+   LTC_OID_DSA,
+   LTC_OID_EC,
+   LTC_OID_EC_PRIMEF,
+   LTC_OID_X25519,
+   LTC_OID_ED25519,
 };
 
 /*
@@ -202,6 +202,17 @@ void ocb3_int_xor_blocks(unsigned char *out, const unsigned char *block_a, const
 
 /* tomcrypt_misc.h */
 
+typedef enum {
+   /** Use `\r\n` as line separator */
+   BASE64_PEM_CRLF = 1,
+   /** Create output with 72 chars line length */
+   BASE64_PEM_SSH = 2,
+} base64_pem_flags;
+
+int base64_encode_pem(const unsigned char *in,  unsigned long inlen,
+                                     char *out, unsigned long *outlen,
+                            unsigned int  flags);
+
 void copy_or_zeromem(const unsigned char* src, unsigned char* dest, unsigned long len, int coz);
 
 int pbes_decrypt(const pbes_arg  *arg, unsigned char *dec_data, unsigned long *dec_size);
@@ -225,6 +236,7 @@ int rsa_init(rsa_key *key);
 void rsa_shrink_key(rsa_key *key);
 int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e,
                       rsa_key *key); /* used by op-tee */
+int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key);
 #endif /* LTC_MRSA */
 
 /* ---- DH Routines ---- */

+ 55 - 10
src/misc/base64/base64_encode.c

@@ -21,23 +21,45 @@ static const char * const codes_base64url =
 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
 #endif /* LTC_BASE64_URL */
 
-static int s_base64_encode_internal(const unsigned char *in,  unsigned long inlen,
-                                 char *out, unsigned long *outlen,
-                                 const char *codes, int pad)
+enum mode {
+   nopad = 0,
+   pad = 1,
+   lf = 2,
+   cr = 4,
+   ssh = 8,
+   crlf = lf | cr,
+};
+
+static int s_base64_encode_internal(const unsigned char *in,    unsigned long inlen,
+                                                   char *out,   unsigned long *outlen,
+                                    const          char *codes, unsigned int  mode)
 {
-   unsigned long i, len2, leven;
+   unsigned long i, len2, leven, linelen;
    char *p;
 
-   LTC_ARGCHK(in     != NULL);
-   LTC_ARGCHK(out    != NULL);
    LTC_ARGCHK(outlen != NULL);
 
+   linelen = (mode & ssh) ? 72 : 64;
+
    /* valid output size ? */
    len2 = 4 * ((inlen + 2) / 3);
+   if ((mode & crlf) == lf) {
+      len2 += len2 / linelen;
+   } else if ((mode & crlf) == crlf) {
+      len2 += (len2 / linelen) * 2;
+   }
    if (*outlen < len2 + 1) {
       *outlen = len2 + 1;
       return CRYPT_BUFFER_OVERFLOW;
    }
+
+   LTC_ARGCHK(in  != NULL);
+   LTC_ARGCHK(out != NULL);
+
+   if ((void*)in == out) {
+      return CRYPT_INVALID_ARG;
+   }
+
    p = out;
    leven = 3*(inlen / 3);
    for (i = 0; i < leven; i += 3) {
@@ -46,6 +68,10 @@ static int s_base64_encode_internal(const unsigned char *in,  unsigned long inle
        *p++ = codes[(((in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F];
        *p++ = codes[in[2] & 0x3F];
        in += 3;
+       if ((p - out) % linelen == 0) {
+          if (mode & cr) *p++ = '\r';
+          if (mode & lf) *p++ = '\n';
+       }
    }
    /* Pad it if necessary...  */
    if (i < inlen) {
@@ -54,7 +80,7 @@ static int s_base64_encode_internal(const unsigned char *in,  unsigned long inle
 
        *p++ = codes[(a >> 2) & 0x3F];
        *p++ = codes[(((a & 3) << 4) + (b >> 4)) & 0x3F];
-       if (pad) {
+       if (mode & pad) {
          *p++ = (i+1 < inlen) ? codes[(((b & 0xf) << 2)) & 0x3F] : '=';
          *p++ = '=';
        }
@@ -83,7 +109,26 @@ static int s_base64_encode_internal(const unsigned char *in,  unsigned long inle
 int base64_encode(const unsigned char *in,  unsigned long inlen,
                                  char *out, unsigned long *outlen)
 {
-    return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, 1);
+    return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, pad);
+}
+
+/**
+   base64 Encode a buffer for PEM output
+     (NUL terminated with line-break at 64 chars)
+   @param in       The input buffer to encode
+   @param inlen    The length of the input buffer
+   @param out      [out] The destination of the base64 encoded data
+   @param outlen   [in/out] The max size and resulting size
+   @param flags    \ref base64_pem_flags
+   @return CRYPT_OK if successful
+*/
+int base64_encode_pem(const unsigned char *in,  unsigned long inlen,
+                                     char *out, unsigned long *outlen,
+                            unsigned int  flags)
+{
+    int use_crlf = flags & BASE64_PEM_CRLF ? pad | crlf : pad | lf;
+    int ssh_style = flags & BASE64_PEM_SSH ? ssh : 0;
+    return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, ssh_style | use_crlf);
 }
 #endif /* LTC_BASE64 */
 
@@ -100,13 +145,13 @@ int base64_encode(const unsigned char *in,  unsigned long inlen,
 int base64url_encode(const unsigned char *in,  unsigned long inlen,
                                     char *out, unsigned long *outlen)
 {
-    return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, 0);
+    return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, nopad);
 }
 
 int base64url_strict_encode(const unsigned char *in,  unsigned long inlen,
                                            char *out, unsigned long *outlen)
 {
-    return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, 1);
+    return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, pad);
 }
 #endif /* LTC_BASE64_URL */
 

+ 6 - 0
src/misc/padding/padding_depad.c

@@ -53,6 +53,12 @@ int padding_depad(const unsigned char *data, unsigned long *length, unsigned lon
          /* nop */
          break;
 #endif
+      case LTC_PAD_SSH:
+         pad = 0x1;
+         for (n = unpadded_length; n < padded_length; ++n) {
+            if (data[n] != pad++) return CRYPT_INVALID_PACKET;
+         }
+         break;
       case LTC_PAD_ONE_AND_ZERO:
          while (unpadded_length > 0 && data[unpadded_length - 1] != 0x80) {
             if (data[unpadded_length - 1] != 0x0) return CRYPT_INVALID_PACKET;

+ 9 - 2
src/misc/padding/padding_pad.c

@@ -32,6 +32,7 @@ static int s_padding_padded_length(unsigned long *length, unsigned long mode)
       case LTC_PAD_PKCS7:
       case LTC_PAD_ONE_AND_ZERO:
       case LTC_PAD_ZERO_ALWAYS:
+      case LTC_PAD_SSH:
          t = 1;
          break;
 #ifdef LTC_RNG_GET_BYTES
@@ -78,10 +79,10 @@ static int s_padding_padded_length(unsigned long *length, unsigned long mode)
 */
 int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode)
 {
-   unsigned long l;
+   unsigned long l, n;
    enum padding_type type;
    int err;
-   unsigned char diff;
+   unsigned char diff, pad;
 
    LTC_ARGCHK(data          != NULL);
    LTC_ARGCHK(padded_length != NULL);
@@ -125,6 +126,12 @@ int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded
          XMEMSET(&data[length], 0, diff-1);
          data[l-1] =  diff;
          break;
+      case LTC_PAD_SSH:
+         pad = 0x1;
+         for (n = length; n < l; ++n) {
+            data[n] = pad++;
+         }
+         break;
       case LTC_PAD_ONE_AND_ZERO:
          XMEMSET(&data[length + 1], 0, diff);
          data[length] =  0x80;

+ 4 - 0
src/pk/asn1/der/short_integer/der_decode_short_integer.c

@@ -42,6 +42,10 @@ int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsig
       return CRYPT_INVALID_PACKET;
    }
 
+   if (len > sizeof(unsigned long)) {
+      return CRYPT_OVERFLOW;
+   }
+
    /* read number */
    y = 0;
    while (len--) {

+ 6 - 6
src/pk/asn1/oid/pk_get_oid.c

@@ -10,12 +10,12 @@ typedef struct {
 } oid_table_entry;
 
 static const oid_table_entry pka_oids[] = {
-                                              { PKA_RSA,       "1.2.840.113549.1.1.1" },
-                                              { PKA_DSA,       "1.2.840.10040.4.1" },
-                                              { PKA_EC,        "1.2.840.10045.2.1" },
-                                              { PKA_EC_PRIMEF, "1.2.840.10045.1.1" },
-                                              { PKA_X25519,    "1.3.101.110" },
-                                              { PKA_ED25519,   "1.3.101.112" },
+                                              { LTC_OID_RSA,       "1.2.840.113549.1.1.1" },
+                                              { LTC_OID_DSA,       "1.2.840.10040.4.1" },
+                                              { LTC_OID_EC,        "1.2.840.10045.2.1" },
+                                              { LTC_OID_EC_PRIMEF, "1.2.840.10045.1.1" },
+                                              { LTC_OID_X25519,    "1.3.101.110" },
+                                              { LTC_OID_ED25519,   "1.3.101.112" },
 };
 
 /*

+ 2 - 1
src/pk/asn1/oid/pk_oid_str.c

@@ -49,7 +49,7 @@ int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID,
    char tmp[256] = { 0 };
 
    LTC_ARGCHK(oid != NULL);
-   LTC_ARGCHK(OID != NULL);
+   LTC_ARGCHK(oidlen < INT_MAX);
    LTC_ARGCHK(outlen != NULL);
 
    for (i = oidlen - 1, k = 0; i >= 0; i--) {
@@ -74,6 +74,7 @@ int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID,
       *outlen = k + 1;
       return CRYPT_BUFFER_OVERFLOW;
    }
+   LTC_ARGCHK(OID != NULL);
    for (j = 0; j < k; j++) OID[j] = tmp[k - j - 1];
    OID[k] = '\0';
    *outlen = k; /* the length without terminating NUL byte */

+ 1 - 1
src/pk/asn1/x509/x509_decode_public_key_from_certificate.c

@@ -81,7 +81,7 @@ int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned lo
                if ((l->type == LTC_ASN1_SEQUENCE)
                      && (l->data != NULL)
                      && LOOKS_LIKE_SPKI(l->child)) {
-                  if (algorithm == PKA_EC) {
+                  if (algorithm == LTC_OID_EC) {
                      err = callback(l->data, l->size, ctx);
                   } else {
                      err = x509_decode_subject_public_key_info(l->data, l->size,

+ 1 - 1
src/pk/dsa/dsa_export.c

@@ -75,7 +75,7 @@ int dsa_export(unsigned char *out, unsigned long *outlen, int type, const dsa_ke
           LTC_SET_ASN1(int_list, 1, LTC_ASN1_INTEGER, key->q, 1UL);
           LTC_SET_ASN1(int_list, 2, LTC_ASN1_INTEGER, key->g, 1UL);
 
-          err = x509_encode_subject_public_key_info(out, outlen, PKA_DSA, tmp,
+          err = x509_encode_subject_public_key_info(out, outlen, LTC_OID_DSA, tmp,
               tmplen, LTC_ASN1_SEQUENCE, int_list,
               sizeof(int_list) / sizeof(int_list[0]));
 

+ 1 - 1
src/pk/dsa/dsa_import.c

@@ -97,7 +97,7 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
       }
 
       len = 3;
-      err = x509_decode_subject_public_key_info(in, inlen, PKA_DSA,
+      err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_DSA,
                                                tmpbuf, &tmpbuf_len,
                                                LTC_ASN1_SEQUENCE, params, &len);
       if (err != CRYPT_OK) {

+ 37 - 36
src/pk/ecc/ecc_export_openssl.c

@@ -34,41 +34,6 @@ int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, cons
 
    if (key->type != PK_PRIVATE && flag_pri) return CRYPT_PK_TYPE_MISMATCH;
 
-   prime = key->dp.prime;
-   order = key->dp.order;
-   b     = key->dp.B;
-   a     = key->dp.A;
-   gx    = key->dp.base.x;
-   gy    = key->dp.base.y;
-
-   /* curve param a */
-   len_a = mp_unsigned_bin_size(a);
-   if (len_a > sizeof(bin_a))                                   { err = CRYPT_BUFFER_OVERFLOW; goto error; }
-   if ((err = mp_to_unsigned_bin(a, bin_a)) != CRYPT_OK)        { goto error; }
-   if (len_a == 0) { len_a = 1; bin_a[0] = 0; } /* handle case a == 0 */
-
-   /* curve param b */
-   len_b = mp_unsigned_bin_size(b);
-   if (len_b > sizeof(bin_b))                                   { err = CRYPT_BUFFER_OVERFLOW; goto error; }
-   if ((err = mp_to_unsigned_bin(b, bin_b)) != CRYPT_OK)        { goto error; }
-   if (len_b == 0) { len_b = 1; bin_b[0] = 0; } /* handle case b == 0 */
-
-   /* base point - (un)compressed based on flag_com */
-   len_g = sizeof(bin_g);
-   err = ltc_ecc_export_point(bin_g, &len_g, gx, gy, key->dp.size, flag_com);
-   if (err != CRYPT_OK)                                         { goto error; }
-
-   /* public key - (un)compressed based on flag_com */
-   len_xy = sizeof(bin_xy);
-   err = ltc_ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp.size, flag_com);
-   if (err != CRYPT_OK)                                         { goto error; }
-
-   /* co-factor */
-   cofactor = key->dp.cofactor;
-
-   /* we support only prime-field EC */
-   if ((err = pk_get_oid(PKA_EC_PRIMEF, &OID)) != CRYPT_OK)     { goto error; }
-
    if (flag_oid) {
       /* http://tools.ietf.org/html/rfc5912
          ECParameters ::= CHOICE {
@@ -79,6 +44,34 @@ int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, cons
       LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_OBJECT_IDENTIFIER, key->dp.oid, key->dp.oidlen);
    }
    else {
+      prime    = key->dp.prime;
+      order    = key->dp.order;
+      a        = key->dp.A;
+      b        = key->dp.B;
+      gx       = key->dp.base.x;
+      gy       = key->dp.base.y;
+      cofactor = key->dp.cofactor;
+
+      /* curve param a */
+      len_a = mp_unsigned_bin_size(a);
+      if (len_a > sizeof(bin_a))                                   { err = CRYPT_BUFFER_OVERFLOW; goto error; }
+      if ((err = mp_to_unsigned_bin(a, bin_a)) != CRYPT_OK)        { goto error; }
+      if (len_a == 0) { len_a = 1; bin_a[0] = 0; } /* handle case a == 0 */
+
+      /* curve param b */
+      len_b = mp_unsigned_bin_size(b);
+      if (len_b > sizeof(bin_b))                                   { err = CRYPT_BUFFER_OVERFLOW; goto error; }
+      if ((err = mp_to_unsigned_bin(b, bin_b)) != CRYPT_OK)        { goto error; }
+      if (len_b == 0) { len_b = 1; bin_b[0] = 0; } /* handle case b == 0 */
+
+      /* base point - (un)compressed based on flag_com */
+      len_g = sizeof(bin_g);
+      err = ltc_ecc_export_point(bin_g, &len_g, gx, gy, key->dp.size, flag_com);
+      if (err != CRYPT_OK)                                         { goto error; }
+
+      /* we support only prime-field EC */
+      if ((err = pk_get_oid(LTC_OID_EC_PRIMEF, &OID)) != CRYPT_OK) { goto error; }
+
       /* http://tools.ietf.org/html/rfc3279
          ECParameters ::= SEQUENCE {                              # SEQUENCE
            version         INTEGER { ecpVer1(1) } (ecpVer1)       # INTEGER       :01
@@ -122,7 +115,15 @@ int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, cons
       LTC_SET_ASN1(&ecparams,    0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
    }
 
+   /* public key - (un)compressed based on flag_com */
+   len_xy = sizeof(bin_xy);
+   err = ltc_ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp.size, flag_com);
+   if (err != CRYPT_OK) {
+      goto error;
+   }
+
    if (flag_pri) {
+
       /* http://tools.ietf.org/html/rfc5915
          ECPrivateKey ::= SEQUENCE {                                    # SEQUENCE
            version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1)  # INTEGER       :01
@@ -155,7 +156,7 @@ int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, cons
            subjectPublicKey  BIT STRING                                 # BIT STRING
          }
       */
-      err = x509_encode_subject_public_key_info( out, outlen, PKA_EC, bin_xy, len_xy,
+      err = x509_encode_subject_public_key_info( out, outlen, LTC_OID_EC, bin_xy, len_xy,
                                                  ecparams.type, ecparams.data, ecparams.size );
    }
 

+ 1 - 1
src/pk/ecc/ecc_import_pkcs8.c

@@ -56,7 +56,7 @@ int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen,
    LTC_ARGCHK(ltc_mp.name != NULL);
 
    /* get EC alg oid */
-   err = pk_get_oid(PKA_EC, &pka_ec_oid);
+   err = pk_get_oid(LTC_OID_EC, &pka_ec_oid);
    if (err != CRYPT_OK) return err;
 
    /* init key */

+ 3 - 3
src/pk/ecc/ecc_import_x509.c

@@ -15,7 +15,7 @@ static int s_ecc_import_x509_with_oid(const unsigned char *in, unsigned long inl
 
    len_xy = sizeof(bin_xy);
    len_oid = 16;
-   err = x509_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy,
+   err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy,
                                              LTC_ASN1_OBJECT_IDENTIFIER, (void *)curveoid, &len_oid);
    if (err == CRYPT_OK) {
       /* load curve parameters for given curve OID */
@@ -63,7 +63,7 @@ static int s_ecc_import_x509_with_curve(const unsigned char *in, unsigned long i
    /* try to load public key */
    len_xy = sizeof(bin_xy);
    len = 6;
-   err = x509_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len);
+   err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len);
 
    if (err == CRYPT_OK) {
       len_a = seq_curve[0].size;
@@ -107,7 +107,7 @@ success:
 int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key)
 {
    return x509_decode_public_key_from_certificate(in, inlen,
-                                                  PKA_EC,
+                                                  LTC_OID_EC,
                                                   LTC_ASN1_EOL, NULL, NULL,
                                                   (public_key_decode_cb)ecc_import_subject_public_key_info, key);
 }

+ 1 - 1
src/pk/ecc/ecc_ssh_ecdsa_encode_name.c

@@ -19,7 +19,7 @@
 */
 int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key)
 {
-   char oidstr[64];
+   char oidstr[64] = {0};
    unsigned long oidlen = sizeof(oidstr);
    int err, size = 0;
 

+ 1 - 1
src/pk/ed25519/ed25519_export.c

@@ -23,7 +23,7 @@ int ed25519_export(       unsigned char *out, unsigned long *outlen,
 {
    LTC_ARGCHK(key != NULL);
 
-   if (key->algo != PKA_ED25519) return CRYPT_PK_INVALID_TYPE;
+   if (key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE;
 
    return ec25519_export(out, outlen, which, key);
 }

+ 2 - 2
src/pk/ed25519/ed25519_import.c

@@ -25,9 +25,9 @@ int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key
    LTC_ARGCHK(key != NULL);
 
    key_len = sizeof(key->pub);
-   if ((err = x509_decode_subject_public_key_info(in, inlen, PKA_ED25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) {
+   if ((err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_ED25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) {
       key->type = PK_PUBLIC;
-      key->algo = PKA_ED25519;
+      key->algo = LTC_OID_ED25519;
    }
    return err;
 }

+ 1 - 1
src/pk/ed25519/ed25519_import_pkcs8.c

@@ -22,7 +22,7 @@ int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
                                   const void *pwd, unsigned long pwdlen,
                               curve25519_key *key)
 {
-   return ec25519_import_pkcs8(in, inlen, pwd, pwdlen, PKA_ED25519, tweetnacl_crypto_sk_to_pk, key);
+   return ec25519_import_pkcs8(in, inlen, pwd, pwdlen, LTC_OID_ED25519, tweetnacl_crypto_sk_to_pk, key);
 }
 
 #endif

+ 1 - 1
src/pk/ed25519/ed25519_import_raw.c

@@ -32,7 +32,7 @@ int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which,
    } else {
       return CRYPT_INVALID_ARG;
    }
-   key->algo = PKA_ED25519;
+   key->algo = LTC_OID_ED25519;
    key->type = which;
 
    return CRYPT_OK;

+ 2 - 2
src/pk/ed25519/ed25519_import_x509.c

@@ -31,13 +31,13 @@ int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519
    LTC_ARGCHK(key != NULL);
 
    if ((err = x509_decode_public_key_from_certificate(in, inlen,
-                                                      PKA_ED25519,
+                                                      LTC_OID_ED25519,
                                                       LTC_ASN1_EOL, NULL, NULL,
                                                       (public_key_decode_cb)s_ed25519_decode, key)) != CRYPT_OK) {
       return err;
    }
    key->type = PK_PUBLIC;
-   key->algo = PKA_ED25519;
+   key->algo = LTC_OID_ED25519;
 
    return err;
 }

+ 1 - 1
src/pk/ed25519/ed25519_make_key.c

@@ -28,7 +28,7 @@ int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key)
    }
 
    key->type = PK_PRIVATE;
-   key->algo = PKA_ED25519;
+   key->algo = LTC_OID_ED25519;
 
    return err;
 }

+ 1 - 1
src/pk/ed25519/ed25519_sign.c

@@ -30,7 +30,7 @@ int ed25519_sign(const unsigned char  *msg, unsigned long msglen,
    LTC_ARGCHK(siglen      != NULL);
    LTC_ARGCHK(private_key != NULL);
 
-   if (private_key->algo != PKA_ED25519) return CRYPT_PK_INVALID_TYPE;
+   if (private_key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE;
    if (private_key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE;
 
    if (*siglen < 64uL) {

+ 1 - 1
src/pk/ed25519/ed25519_verify.c

@@ -34,7 +34,7 @@ int ed25519_verify(const  unsigned char *msg, unsigned long msglen,
    *stat = 0;
 
    if (siglen != 64uL) return CRYPT_INVALID_ARG;
-   if (public_key->algo != PKA_ED25519) return CRYPT_PK_INVALID_TYPE;
+   if (public_key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE;
 
    mlen = msglen + siglen;
    if ((mlen < msglen) || (mlen < siglen)) return CRYPT_OVERFLOW;

+ 1 - 1
src/pk/rsa/rsa_export.c

@@ -78,7 +78,7 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, const rsa_ke
       }
 
       err = x509_encode_subject_public_key_info(out, outlen,
-        PKA_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0);
+        LTC_OID_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0);
 
 finish:
       if (tmp != out) XFREE(tmp);

+ 70 - 46
src/pk/rsa/rsa_import.c

@@ -9,8 +9,74 @@
 
 #ifdef LTC_MRSA
 
+
+/**
+  Import an RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only]
+
+    The `key` passed into this function has to be already initialized and will
+    NOT be free'd on error!
+
+  @param in      The packet to import from
+  @param inlen   It's length (octets)
+  @param key     [out] Destination for newly imported key
+  @return CRYPT_OK if successful
+*/
+int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+   int   err;
+   unsigned long version = -1;
+
+   err = der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version,
+                                              LTC_ASN1_EOL,     0UL, NULL);
+
+   if (err == CRYPT_OVERFLOW) {
+      /* the version would fit into an LTC_ASN1_SHORT_INTEGER
+       * so we try to decode as a public key
+       */
+      if ((err = der_decode_sequence_multi(in, inlen,
+                                     LTC_ASN1_INTEGER, 1UL, key->N,
+                                     LTC_ASN1_INTEGER, 1UL, key->e,
+                                     LTC_ASN1_EOL,     0UL, NULL)) == CRYPT_OK) {
+         key->type = PK_PUBLIC;
+      }
+      goto LBL_OUT;
+   } else if (err != CRYPT_INPUT_TOO_LONG) {
+      /* couldn't decode the version, so error out */
+      goto LBL_OUT;
+   }
+
+   if (version == 0) {
+      /* it's a private key */
+      if ((err = der_decode_sequence_multi(in, inlen,
+                          LTC_ASN1_SHORT_INTEGER, 1UL, &version,
+                          LTC_ASN1_INTEGER, 1UL, key->N,
+                          LTC_ASN1_INTEGER, 1UL, key->e,
+                          LTC_ASN1_INTEGER, 1UL, key->d,
+                          LTC_ASN1_INTEGER, 1UL, key->p,
+                          LTC_ASN1_INTEGER, 1UL, key->q,
+                          LTC_ASN1_INTEGER, 1UL, key->dP,
+                          LTC_ASN1_INTEGER, 1UL, key->dQ,
+                          LTC_ASN1_INTEGER, 1UL, key->qP,
+                          LTC_ASN1_EOL,     0UL, NULL)) != CRYPT_OK) {
+         goto LBL_OUT;
+      }
+      key->type = PK_PRIVATE;
+   } else if (version == 1) {
+      /* we don't support multi-prime RSA */
+      err = CRYPT_PK_INVALID_TYPE;
+      goto LBL_OUT;
+   }
+   err = CRYPT_OK;
+LBL_OUT:
+   return err;
+}
+
 /**
-  Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in PKCS #1 v2.1]
+  Import multiple formats of RSA public and private keys.
+
+     RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only]
+     SubjectPublicKeyInfo formatted public keys
+
   @param in      The packet to import from
   @param inlen   It's length (octets)
   @param key     [out] Destination for newly imported key
@@ -19,7 +85,6 @@
 int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
 {
    int           err;
-   void         *zero;
    unsigned char *tmpbuf=NULL;
    unsigned long tmpbuf_len, len;
 
@@ -42,7 +107,7 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
 
    len = 0;
    err = x509_decode_subject_public_key_info(in, inlen,
-        PKA_RSA, tmpbuf, &tmpbuf_len,
+        LTC_OID_RSA, tmpbuf, &tmpbuf_len,
         LTC_ASN1_NULL, NULL, &len);
 
    if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */
@@ -60,50 +125,9 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
    }
 
    /* not SSL public key, try to match against PKCS #1 standards */
-   err = der_decode_sequence_multi(in, inlen, LTC_ASN1_INTEGER, 1UL, key->N,
-                                              LTC_ASN1_EOL,     0UL, NULL);
-
-   if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
-      goto LBL_ERR;
-   }
-
-   if (mp_cmp_d(key->N, 0) == LTC_MP_EQ) {
-      if ((err = mp_init(&zero)) != CRYPT_OK) {
-         goto LBL_ERR;
-      }
-      /* it's a private key */
-      if ((err = der_decode_sequence_multi(in, inlen,
-                          LTC_ASN1_INTEGER, 1UL, zero,
-                          LTC_ASN1_INTEGER, 1UL, key->N,
-                          LTC_ASN1_INTEGER, 1UL, key->e,
-                          LTC_ASN1_INTEGER, 1UL, key->d,
-                          LTC_ASN1_INTEGER, 1UL, key->p,
-                          LTC_ASN1_INTEGER, 1UL, key->q,
-                          LTC_ASN1_INTEGER, 1UL, key->dP,
-                          LTC_ASN1_INTEGER, 1UL, key->dQ,
-                          LTC_ASN1_INTEGER, 1UL, key->qP,
-                          LTC_ASN1_EOL,     0UL, NULL)) != CRYPT_OK) {
-         mp_clear(zero);
-         goto LBL_ERR;
-      }
-      mp_clear(zero);
-      key->type = PK_PRIVATE;
-   } else if (mp_cmp_d(key->N, 1) == LTC_MP_EQ) {
-      /* we don't support multi-prime RSA */
-      err = CRYPT_PK_INVALID_TYPE;
-      goto LBL_ERR;
-   } else {
-      /* it's a public key and we lack e */
-      if ((err = der_decode_sequence_multi(in, inlen,
-                                     LTC_ASN1_INTEGER, 1UL, key->N,
-                                     LTC_ASN1_INTEGER, 1UL, key->e,
-                                     LTC_ASN1_EOL,     0UL, NULL)) != CRYPT_OK) {
-         goto LBL_ERR;
-      }
-      key->type = PK_PUBLIC;
+   if ((err = rsa_import_pkcs1(in, inlen, key)) == CRYPT_OK) {
+      goto LBL_FREE;
    }
-   err = CRYPT_OK;
-   goto LBL_FREE;
 
 LBL_ERR:
    rsa_free(key);

+ 9 - 22
src/pk/rsa/rsa_import_pkcs8.c

@@ -46,10 +46,9 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
                      rsa_key *key)
 {
    int           err;
-   void          *zero, *iter;
    unsigned char *buf1 = NULL, *buf2 = NULL;
    unsigned long buf1len, buf2len;
-   unsigned long oid[16];
+   unsigned long oid[16], version;
    const char    *rsaoid;
    ltc_asn1_list alg_seq[2], top_seq[3];
    ltc_asn1_list *l = NULL;
@@ -61,7 +60,7 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
    LTC_ARGCHK(ltc_mp.name != NULL);
 
    /* get RSA alg oid */
-   err = pk_get_oid(PKA_RSA, &rsaoid);
+   err = pk_get_oid(LTC_OID_RSA, &rsaoid);
    if (err != CRYPT_OK) { goto LBL_NOFREE; }
 
    /* alloc buffers */
@@ -72,9 +71,8 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
    buf2 = XMALLOC(buf2len);
    if (buf2 == NULL) { err = CRYPT_MEM; goto LBL_FREE1; }
 
-   if ((err = mp_init_multi(&zero, &iter, NULL)) != CRYPT_OK) { goto LBL_FREE2; }
    /* init key */
-   if ((err = rsa_init(key)) != CRYPT_OK) { goto LBL_FREE3; }
+   if ((err = rsa_init(key)) != CRYPT_OK) { goto LBL_FREE2; }
 
    /* try to decode encrypted priv key */
    if ((err = pkcs8_decode_flexi(in, inlen, passwd, passwdlen, &l)) != CRYPT_OK) {
@@ -86,7 +84,7 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
    /* try to decode unencrypted priv key */
    LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL);
    LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_NULL, NULL, 0UL);
-   LTC_SET_ASN1(top_seq, 0, LTC_ASN1_INTEGER, zero, 1UL);
+   LTC_SET_ASN1(top_seq, 0, LTC_ASN1_SHORT_INTEGER, &version, 1UL);
    LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL);
    LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len);
    err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL);
@@ -97,28 +95,17 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
       goto LBL_ERR;
    }
 
-   err = der_decode_sequence_multi(buf1, top_seq[2].size,
-                                   LTC_ASN1_INTEGER, 1UL, zero,
-                                   LTC_ASN1_INTEGER, 1UL, key->N,
-                                   LTC_ASN1_INTEGER, 1UL, key->e,
-                                   LTC_ASN1_INTEGER, 1UL, key->d,
-                                   LTC_ASN1_INTEGER, 1UL, key->p,
-                                   LTC_ASN1_INTEGER, 1UL, key->q,
-                                   LTC_ASN1_INTEGER, 1UL, key->dP,
-                                   LTC_ASN1_INTEGER, 1UL, key->dQ,
-                                   LTC_ASN1_INTEGER, 1UL, key->qP,
-                                   LTC_ASN1_EOL,     0UL, NULL);
-   if (err != CRYPT_OK) { goto LBL_ERR; }
+   if ((err = rsa_import_pkcs1(buf1, top_seq[2].size, key)) != CRYPT_OK) {
+      goto LBL_ERR;
+   }
    key->type = PK_PRIVATE;
    err = CRYPT_OK;
-   goto LBL_FREE3;
+   goto LBL_FREE2;
 
 LBL_ERR:
    rsa_free(key);
-LBL_FREE3:
-   mp_clear_multi(iter, zero, NULL);
-   if (l) der_free_sequence_flexi(l);
 LBL_FREE2:
+   if (l) der_free_sequence_flexi(l);
    XFREE(buf2);
 LBL_FREE1:
    XFREE(buf1);

+ 1 - 1
src/pk/rsa/rsa_import_x509.c

@@ -39,7 +39,7 @@ int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key)
    }
 
    if ((err = x509_decode_public_key_from_certificate(in, inlen,
-                                                      PKA_RSA, LTC_ASN1_NULL,
+                                                      LTC_OID_RSA, LTC_ASN1_NULL,
                                                       NULL, NULL,
                                                       (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) {
       rsa_free(key);

+ 1 - 1
src/pk/x25519/x25519_export.c

@@ -23,7 +23,7 @@ int x25519_export(      unsigned char *out, unsigned long *outlen,
 {
    LTC_ARGCHK(key != NULL);
 
-   if (key->algo != PKA_X25519) return CRYPT_PK_INVALID_TYPE;
+   if (key->algo != LTC_OID_X25519) return CRYPT_PK_INVALID_TYPE;
 
    return ec25519_export(out, outlen, which, key);
 }

+ 2 - 2
src/pk/x25519/x25519_import.c

@@ -25,9 +25,9 @@ int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *
    LTC_ARGCHK(key != NULL);
 
    key_len = sizeof(key->pub);
-   if ((err = x509_decode_subject_public_key_info(in, inlen, PKA_X25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) {
+   if ((err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_X25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) {
       key->type = PK_PUBLIC;
-      key->algo = PKA_X25519;
+      key->algo = LTC_OID_X25519;
    }
    return err;
 }

+ 1 - 1
src/pk/x25519/x25519_import_pkcs8.c

@@ -22,7 +22,7 @@ int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
                        const void *pwd, unsigned long pwdlen,
                        curve25519_key *key)
 {
-   return ec25519_import_pkcs8(in, inlen, pwd, pwdlen, PKA_X25519, tweetnacl_crypto_scalarmult_base, key);
+   return ec25519_import_pkcs8(in, inlen, pwd, pwdlen, LTC_OID_X25519, tweetnacl_crypto_scalarmult_base, key);
 }
 
 #endif

+ 1 - 1
src/pk/x25519/x25519_import_raw.c

@@ -32,7 +32,7 @@ int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, c
    } else {
       return CRYPT_INVALID_ARG;
    }
-   key->algo = PKA_X25519;
+   key->algo = LTC_OID_X25519;
    key->type = which;
 
    return CRYPT_OK;

+ 2 - 2
src/pk/x25519/x25519_import_x509.c

@@ -31,13 +31,13 @@ int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_
    LTC_ARGCHK(key != NULL);
 
    if ((err = x509_decode_public_key_from_certificate(in, inlen,
-                                                      PKA_X25519,
+                                                      LTC_OID_X25519,
                                                       LTC_ASN1_EOL, NULL, NULL,
                                                       (public_key_decode_cb)s_x25519_decode, key)) != CRYPT_OK) {
       return err;
    }
    key->type = PK_PUBLIC;
-   key->algo = PKA_X25519;
+   key->algo = LTC_OID_X25519;
 
    return err;
 }

+ 1 - 1
src/pk/x25519/x25519_make_key.c

@@ -34,7 +34,7 @@ int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key)
    tweetnacl_crypto_scalarmult_base(key->pub, key->priv);
 
    key->type = PK_PRIVATE;
-   key->algo = PKA_X25519;
+   key->algo = LTC_OID_X25519;
 
    return err;
 }

+ 24 - 3
tests/base64_test.c

@@ -15,6 +15,11 @@ int base64_test(void)
          0xbe, 0xe8, 0x92, 0x3c, 0xa2, 0x25, 0xf0, 0xf8,
          0x91, 0xe4, 0xef, 0xab, 0x0b, 0x8c, 0xfd, 0xff,
          0x14, 0xd0, 0x29, 0x9d, 0x00 };
+   /* 3 A's are encoded as QUFB */
+   const char *As_lf = "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB\nQUFB";
+   const char *As_crlf = "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB\r\nQUFB";
+   const char *As_ssh_lf = "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB\nQUFB";
+   const char *As_ssh_crlf = "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB\r\nQUFB";
 
 #if defined(LTC_BASE64)
    /*
@@ -140,16 +145,32 @@ int base64_test(void)
 
    out[10] = 0;
    DO(base64_decode(out, l1, tmp, &l2));
-   DO(compare_testvector(tmp, l2, in, l2, "insane base64 decoding (NUL)", -1));
+   DO(compare_testvector(tmp, l2, in, l2, "insane base64 decoding (NUL)", 0));
    DO(base64_sane_decode(out, l1, tmp, &l2) == CRYPT_INVALID_PACKET ? CRYPT_OK : CRYPT_INVALID_PACKET);
    DO(base64_strict_decode(out, l1, tmp, &l2) == CRYPT_INVALID_PACKET ? CRYPT_OK : CRYPT_INVALID_PACKET);
 
    out[10] = 9; /* tab */
    DO(base64_decode(out, l1, tmp, &l2));
-   DO(compare_testvector(tmp, l2, in, l2, "insane base64 decoding (TAB)", -1));
+   DO(compare_testvector(tmp, l2, in, l2, "insane base64 decoding (TAB)", 0));
    DO(base64_sane_decode(out, l1, tmp, &l2));
-   DO(compare_testvector(tmp, l2, in, l2, "relaxed base64 decoding (TAB)", -1));
+   DO(compare_testvector(tmp, l2, in, l2, "relaxed base64 decoding (TAB)", 0));
    DO(base64_strict_decode(out, l1, tmp, &l2) == CRYPT_INVALID_PACKET ? CRYPT_OK : CRYPT_INVALID_PACKET);
+
+   memset(in, 'A', sizeof(in));
+   l1 = strlen(As_lf);
+   SHOULD_FAIL(base64_encode_pem(in, 51, out, &l1, 0));
+   l1++;
+   DO(base64_encode_pem(in, 51, out, &l1, 0));
+   DO(compare_testvector(out, l1, As_lf, strlen(As_lf), "PEM output with \\n", 0));
+   l1 = strlen(As_crlf) + 1;
+   DO(base64_encode_pem(in, 51, out, &l1, BASE64_PEM_CRLF));
+   DO(compare_testvector(out, l1, As_crlf, strlen(As_crlf), "PEM output with \\r\\n", 0));
+   l1 = strlen(As_ssh_lf) + 1;
+   DO(base64_encode_pem(in, 57, out, &l1, BASE64_PEM_SSH));
+   DO(compare_testvector(out, l1, As_ssh_lf, strlen(As_ssh_lf), "PEM SSH-style output with \\n", 0));
+   l1 = strlen(As_ssh_crlf) + 1;
+   DO(base64_encode_pem(in, 57, out, &l1, BASE64_PEM_SSH | BASE64_PEM_CRLF));
+   DO(compare_testvector(out, l1, As_ssh_crlf, strlen(As_ssh_crlf), "PEM SSH-style output with \\r\\n", 0));
 #endif
 
    return 0;

+ 2 - 1
tests/common.c

@@ -120,7 +120,7 @@ int test_process_dir(const char *path, void *ctx, dir_iter_cb process, dir_clean
 #if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1
          fprintf(stderr, "%s: Skip: %s\n", test, fname);
 #endif
-         break;
+         goto continue_loop;
       } else if (err != CRYPT_OK) {
 #if defined(LTC_TEST_DBG)
          fprintf(stderr, "%s: Test %s failed (cause: %s).\n\n", test, fname, error_to_string(err));
@@ -133,6 +133,7 @@ int test_process_dir(const char *path, void *ctx, dir_iter_cb process, dir_clean
          cleanup(ctx);
       }
 
+continue_loop:
       XFREE(buf);
       buf = NULL;
       fclose(f);

+ 70 - 18
tests/der_test.c

@@ -229,19 +229,45 @@ SEQUENCE(3 elem)
 #define CHECK_ASN1_HAS_NO_DATA(l) CHECK_ASN1_HAS_NO(l, data)
 
 #ifdef LTC_DER_TESTS_PRINT_FLEXI
+
+static void* s_xmalloc(int l)
+{
+   void *r = XMALLOC(l);
+
+#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 3
+   fprintf(stderr, "ALLOC %9d to %p\n", l, r);
+#endif
+   if (!r) {
+      fprintf(stderr, "Could not allocate %d bytes of memory\n", l);
+      exit(EXIT_FAILURE);
+   }
+   return r;
+}
+
+static void s_free(void *p)
+{
+#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 3
+   fprintf(stderr, "FREE %p\n", p);
+#endif
+   XFREE(p);
+}
+
 static void s_der_tests_print_flexi(ltc_asn1_list* l, unsigned int level)
 {
-  char buf[1024];
+  char *buf = NULL;
   const char* name = NULL;
   const char* text = NULL;
   ltc_asn1_list* ostring = NULL;
   unsigned int n;
+  int slen;
 
   switch (l->type)
     {
   case LTC_ASN1_EOL:
     name = "EOL";
-    snprintf(buf, sizeof(buf),__ASN1_FMTSTRING_FMT "\n", ASN1_FMTSTRING_VAL(l));
+    slen = snprintf(NULL, 0, ASN1_FMTSTRING_FMT "\n", ASN1_FMTSTRING_VAL(l));
+    buf = s_xmalloc(slen);
+    slen = snprintf(buf, slen, ASN1_FMTSTRING_FMT "\n", ASN1_FMTSTRING_VAL(l));
     text = buf;
     break;
   case LTC_ASN1_BOOLEAN:
@@ -255,6 +281,7 @@ static void s_der_tests_print_flexi(ltc_asn1_list* l, unsigned int level)
     break;
   case LTC_ASN1_INTEGER:
     name = "INTEGER";
+    buf = s_xmalloc(((mp_get_digit_count(l->data) + 1) * ltc_mp.bits_per_digit) / 3);
     mp_toradix(l->data, buf, 10);
     text = buf;
     break;
@@ -273,11 +300,10 @@ static void s_der_tests_print_flexi(ltc_asn1_list* l, unsigned int level)
        */
       if (der_decode_sequence_flexi(l->data, &ostring_l, &ostring) == CRYPT_OK) {
           text = "";
-      }
-      else {
+      } else {
           int r;
-          char* s = buf;
-          int sz = sizeof(buf);
+          int sz = l->size * 2 + 1;
+          char* s = buf = s_xmalloc(sz);
           for (n = 0; n < l->size; ++n) {
               r = snprintf(s, sz, "%02X", ((unsigned char*)l->data)[n]);
               if (r < 0 || r >= sz) {
@@ -298,7 +324,12 @@ static void s_der_tests_print_flexi(ltc_asn1_list* l, unsigned int level)
   case LTC_ASN1_OBJECT_IDENTIFIER:
     name = "OBJECT IDENTIFIER";
     {
-      unsigned long len = sizeof(buf);
+      unsigned long len = 0;
+      if (pk_oid_num_to_str(l->data, l->size, buf, &len) != CRYPT_BUFFER_OVERFLOW) {
+        fprintf(stderr, "%s WTF\n", name);
+        exit(EXIT_FAILURE);
+      }
+      buf = s_xmalloc(len);
       if (pk_oid_num_to_str(l->data, l->size, buf, &len) != CRYPT_OK) {
         fprintf(stderr, "%s boom\n", name);
         exit(EXIT_FAILURE);
@@ -321,7 +352,9 @@ static void s_der_tests_print_flexi(ltc_asn1_list* l, unsigned int level)
     name = "UTCTIME";
     {
       ltc_utctime* ut = l->data;
-      snprintf(buf, sizeof(buf), "%02d-%02d-%02d %02d:%02d:%02d %c%02d:%02d",
+      slen = 32;
+      buf = s_xmalloc(slen);
+      snprintf(buf, slen, "%02d-%02d-%02d %02d:%02d:%02d %c%02d:%02d",
           ut->YY, ut->MM, ut->DD, ut->hh, ut->mm, ut->ss,
           ut->off_dir ? '-' : '+', ut->off_hh, ut->off_mm);
       text = buf;
@@ -331,11 +364,13 @@ static void s_der_tests_print_flexi(ltc_asn1_list* l, unsigned int level)
     name = "GENERALIZED TIME";
     {
       ltc_generalizedtime* gt = l->data;
+      slen = 32;
+      buf = s_xmalloc(slen);
       if(gt->fs)
-         snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d.%02dZ",
+         snprintf(buf, slen, "%04d-%02d-%02d %02d:%02d:%02d.%02dZ",
           gt->YYYY, gt->MM, gt->DD, gt->hh, gt->mm, gt->ss, gt->fs);
       else
-         snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02dZ",
+         snprintf(buf, slen, "%04d-%02d-%02d %02d:%02d:%02dZ",
           gt->YYYY, gt->MM, gt->DD, gt->hh, gt->mm, gt->ss);
       text = buf;
     }
@@ -366,8 +401,8 @@ static void s_der_tests_print_flexi(ltc_asn1_list* l, unsigned int level)
     name = "NON STANDARD";
     {
        int r;
-       char* s = buf;
-       int sz = sizeof(buf);
+       int sz = 128;
+       char* s = buf = s_xmalloc(sz);
 
        r = snprintf(s, sz, "[%s %s %llu]", der_asn1_class_to_string_map[l->klass], der_asn1_pc_to_string_map[l->pc], l->tag);
        if (r < 0 || r >= sz) {
@@ -394,6 +429,11 @@ static void s_der_tests_print_flexi(ltc_asn1_list* l, unsigned int level)
   else
      fprintf(stderr, "WTF type=%i\n", l->type);
 
+  if (buf) {
+     s_free(buf);
+     buf = NULL;
+  }
+
   if (ostring) {
       s_der_tests_print_flexi(ostring, level + 1);
       der_free_sequence_flexi(ostring);
@@ -1661,7 +1701,7 @@ int der_test(void)
       for (z = 0; z < 1024; z++) {
 #endif
          if (yarrow_read(buf[0], z, &yarrow_prng) != z) {
-            fprintf(stderr, "Failed to read %lu bytes from yarrow\n", z);
+            fprintf(stderr, "%d: Failed to read %lu bytes from yarrow\n", __LINE__, z);
             return 1;
          }
          DO(mp_read_unsigned_bin(a, buf[0], z));
@@ -1684,7 +1724,7 @@ int der_test(void)
    for (zz = 0; zz < 256; zz++) {
       for (z = 1; z < 4; z++) {
          if (yarrow_read(buf[2], z, &yarrow_prng) != z) {
-            fprintf(stderr, "Failed to read %lu bytes from yarrow\n", z);
+            fprintf(stderr, "%d: Failed to read %lu bytes from yarrow\n", __LINE__, z);
             return 1;
          }
          /* encode with normal */
@@ -1723,7 +1763,10 @@ int der_test(void)
 
 /* Test bit string */
    for (zz = 1; zz < 1536; zz++) {
-       yarrow_read(buf[0], zz, &yarrow_prng);
+       if (yarrow_read(buf[0], zz, &yarrow_prng) != zz) {
+          fprintf(stderr, "%d: Failed to read %lu bytes from yarrow\n", __LINE__, zz);
+          return 1;
+       }
        for (z = 0; z < zz; z++) {
            buf[0][z] &= 0x01;
        }
@@ -1745,7 +1788,10 @@ int der_test(void)
 
 /* Test octet string */
    for (zz = 1; zz < 1536; zz++) {
-       yarrow_read(buf[0], zz, &yarrow_prng);
+       if (yarrow_read(buf[0], zz, &yarrow_prng) != zz) {
+          fprintf(stderr, "%d: Failed to read %lu bytes from yarrow\n", __LINE__, zz);
+          return 1;
+       }
        x = sizeof(buf[1]);
        DO(der_encode_octet_string(buf[0], zz, buf[1], &x));
        DO(der_length_octet_string(zz, &y));
@@ -1783,7 +1829,10 @@ int der_test(void)
    /* do random strings */
    for (zz = 0; zz < 5000; zz++) {
        /* pick a random number of words */
-       yarrow_read(buf[0], 4, &yarrow_prng);
+       if (yarrow_read(buf[0], 4, &yarrow_prng) != 4) {
+          fprintf(stderr, "%d: Failed to read %d bytes from yarrow\n", __LINE__, 4);
+          return 1;
+       }
        LOAD32L(z, buf[0]);
        z = 2 + (z % ((sizeof(oid[0])/sizeof(oid[0][0])) - 2));
 
@@ -1792,7 +1841,10 @@ int der_test(void)
        oid[0][1] = buf[0][1] % 40;
 
        for (y = 2; y < z; y++) {
-          yarrow_read(buf[0], 4, &yarrow_prng);
+          if (yarrow_read(buf[0], 4, &yarrow_prng) != 4) {
+             fprintf(stderr, "%d: Failed to read %d bytes from yarrow\n", __LINE__, 4);
+             return 1;
+          }
           LOAD32L(oid[0][y], buf[0]);
        }
 

+ 19 - 0
tests/padding_test.c

@@ -88,6 +88,18 @@ static int s_cmp_zero(const padding_testcase* t, const unsigned char* p, unsigne
    return CRYPT_OK;
 }
 
+static int s_cmp_ssh(const padding_testcase* t, const unsigned char* p, unsigned long len)
+{
+   unsigned long n, diff = len - t->is;
+   unsigned char pad = 0x1;
+   DOX(EQ(len, t->should), t->name);
+   for (n = len - diff; n < len; ++n) {
+      DOX(EQ(p[n], pad), t->name);
+      pad++;
+   }
+   return CRYPT_OK;
+}
+
 static int s_padding_testrun(const padding_testcase* t)
 {
    unsigned long len;
@@ -126,6 +138,13 @@ int padding_test(void)
                              { 255, 256,   0, LTC_PAD_ANSI_X923 | 16, "255-x923", s_cmp_x923 },
                              { 256, 272,   0, LTC_PAD_ANSI_X923 | 16, "256-x923", s_cmp_x923 },
 
+                             {   0,  16,   0, LTC_PAD_SSH | 16, "0-ssh",   s_cmp_ssh },
+                             {   1,  16,   0, LTC_PAD_SSH | 16, "1-ssh",   s_cmp_ssh },
+                             {  15,  16,   0, LTC_PAD_SSH | 16, "15-ssh",  s_cmp_ssh },
+                             {  16,  32,   0, LTC_PAD_SSH | 16, "16-ssh",  s_cmp_ssh },
+                             { 255, 256,   0, LTC_PAD_SSH | 16, "255-ssh", s_cmp_ssh },
+                             { 256, 272,   0, LTC_PAD_SSH | 16, "256-ssh", s_cmp_ssh },
+
                              {   0,  16,   0, LTC_PAD_ONE_AND_ZERO | 16, "0-one-and-zero",   s_cmp_oaz },
                              {   1,  16,   0, LTC_PAD_ONE_AND_ZERO | 16, "1-one-and-zero",   s_cmp_oaz },
                              {  15,  16,   0, LTC_PAD_ONE_AND_ZERO | 16, "15-one-and-zero",  s_cmp_oaz },