[openssl-users] Building an application with OpenSSL and FIPS support.

Matthew Heimlich MHeimlich at Steelcloud.com
Fri Oct 7 20:37:01 UTC 2016


Running fails specifically on the line:


if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();


Although I've added some additional debugging code at this point, including this function:


int Check_Enable_FIPS(void)
{
    int mode = FIPS_mode();
    int ret = 0;
    unsigned long err = 0;

    if(mode == 0)
    {
        ret = FIPS_mode_set(1 /* on */);
        printf("Attempting to set FIPS mode to 1...\n");
        err = ERR_peek_last_error();
        printf("Last error was: %lx\n", err);
        if(ret != 1)
        {
            err = ERR_get_error();
        }
    } else {
        ret = FIPS_mode_set(0 /* off */);
        if(ret != 1)
        {
            err = ERR_get_error();
        }
    }

    if(ret != 1)
    {
        printf("FIPS_mode_set failed: %lx\n", err);
    }


    printf("FIPS mode is: %d\n", FIPS_mode());
}​​

Which returns


Attempting to set FIPS mode to 1...
Last error was: 2d06b06f
FIPS_mode_set failed: 2d06b06f
FIPS mode is: 0​


So it would appear that my FIPS mode is never even being set, and walking through the code would seem to confirm this. In addition, the error code doesn't seem to be present in the FIPS documentation, but errstr informs me that it is


error:2D06B06F:FIPS routines:DSA_BUILTIN_PARAMGEN2:fingerprint does not match nonpic relocated​



Any tips on where to go from here?

Thanks,

Matt Heimlich
________________________________
From: openssl-users <openssl-users-bounces at openssl.org> on behalf of Ethan Rahn <ethan.rahn at gmail.com>
Sent: Friday, October 7, 2016 4:01 PM
To: openssl-users at openssl.org
Subject: Re: [openssl-users] Building an application with OpenSSL and FIPS support.

Matt,

What part of the selftest fails? Can you step through it with a debugger?

Cheers,

Ethan

On Fri, Oct 7, 2016 at 10:56 AM, Matthew Heimlich <MHeimlich at steelcloud.com<mailto:MHeimlich at steelcloud.com>> wrote:

I'm on RHEL7. I've got a very simple encryption/decryption program that works fine without FIPS support enabled, but fails when it is:

#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>

void handleErrors(void)
{
    ERR_print_errors_fp(stderr);
    abort();
}

    int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
    unsigned char *iv, unsigned char *ciphertext)
{
  EVP_CIPHER_CTX *ctx;

  int len;

  int ciphertext_len;

  /* Create and initialise the context */
  if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

  /* Initialise the encryption operation. IMPORTANT - ensure you use a key
   * and IV size appropriate for your cipher
   * In this example we are using 256 bit AES (i.e. a 256 bit key). The
   * IV size for *most* modes is the same as the block size. For AES this
   * is 128 bits */
  if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
    handleErrors();

  /* Provide the message to be encrypted, and obtain the encrypted output.
   * EVP_EncryptUpdate can be called multiple times if necessary
   */
  if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
    handleErrors();
  ciphertext_len = len;

  /* Finalise the encryption. Further ciphertext bytes may be written at
   * this stage.
   */
  if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
  ciphertext_len += len;

  /* Clean up */
  EVP_CIPHER_CTX_free(ctx);

  return ciphertext_len;
}

int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
  unsigned char *iv, unsigned char *plaintext)
{
  EVP_CIPHER_CTX *ctx;

  int len;

  int plaintext_len;

  /* Create and initialise the context */
  if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

  /* Initialise the decryption operation. IMPORTANT - ensure you use a key
   * and IV size appropriate for your cipher
   * In this example we are using 256 bit AES (i.e. a 256 bit key). The
   * IV size for *most* modes is the same as the block size. For AES this
   * is 128 bits */
  if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
    handleErrors();

  /* Provide the message to be decrypted, and obtain the plaintext output.
   * EVP_DecryptUpdate can be called multiple times if necessary
   */
  if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
    handleErrors();
  plaintext_len = len;

  /* Finalise the decryption. Further plaintext bytes may be written at
   * this stage.
   */
  if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors();
  plaintext_len += len;

  /* Clean up */
  EVP_CIPHER_CTX_free(ctx);

  return plaintext_len;
}

int main (void)
{
  /* Force FIPS initialization */
  FIPS_mode_set(1);
  /* Set up the key and iv. Do I need to say to not hard code these in a
   * real application? :-)
   */

  /* A 256 bit key */
  unsigned char *key = (unsigned char *)"01234567890123456789012345678901";

  /* A 128 bit IV */
  unsigned char *iv = (unsigned char *)"01234567890123456";

  /* Message to be encrypted */
  unsigned char *plaintext =
                (unsigned char *)"The quick brown fox jumps over the lazy dog";

  /* Buffer for ciphertext. Ensure the buffer is long enough for the
   * ciphertext which may be longer than the plaintext, dependant on the
   * algorithm and mode
   */
  unsigned char ciphertext[128];

  /* Buffer for the decrypted text */
  unsigned char decryptedtext[128];

  int decryptedtext_len, ciphertext_len;

  /* Initialise the library */
  ERR_load_crypto_strings();
  OpenSSL_add_all_algorithms();
  OPENSSL_config(NULL);

  /* Encrypt the plaintext */
  ciphertext_len = encrypt (plaintext, strlen ((char *)plaintext), key, iv,
                            ciphertext);

  /* Do something useful with the ciphertext here */
  printf("Ciphertext is:\n");
  BIO_dump_fp (stdout, (const char *)ciphertext, ciphertext_len);

  /* Decrypt the ciphertext */
  decryptedtext_len = decrypt(ciphertext, ciphertext_len, key, iv,
    decryptedtext);

  /* Add a NULL terminator. We are expecting printable text */
  decryptedtext[decryptedtext_len] = '\0';

  /* Show the decrypted text */
  printf("Decrypted text is:\n");
  printf("%s\n", decryptedtext);

  /* Clean up */
  EVP_cleanup();
  ERR_free_strings();

  return 0;
}


As you can see, just the demo code with FIPS enabled. Without FIPS, my output is:

Ciphertext is:
0000 - e0 6f 63 a7 11 e8 b7 aa-9f 94 40 10 7d 46 80 a1   .oc....... at .}F..
0010 - 17 99 43 80 ea 31 d2 a2-99 b9 53 02 d4 39 b9 70   ..C..1....S..9.p
0020 - 2c 8e 65 a9 92 36 ec 92-07 04 91 5c f1 a9 8a 44   ,.e..6.....\...D
Decrypted text is:
The quick brown fox jumps over the lazy dog


With FIPS, compilation goes fine, but generates the following when run:

139686960322208:error:2D0A0086:FIPS routines:FIPS_cipher:selftest failed:fips_enc.c:336:
139686960322208:error:2D0A0086:FIPS routines:FIPS_cipher:selftest failed:fips_enc.c:336:


I've tried both as a C project, and as a C++ project, pointing the CC env variable at both the fipsld script, and the modified fipsld++ from the wiki script as appropriate. My FIPSLD_CC variable points to gcc as noted in the FIPS documentation.

What am I missing here?​



Thanks,

Matt Heimlich ​

--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mta.openssl.org/pipermail/openssl-users/attachments/20161007/8c5754f2/attachment-0001.html>


More information about the openssl-users mailing list