Hi All,

In our application, net-snmp library is used for making snmpget calls and 
processing snmp traps. it works perfectly.
But with enabling OpenSSL FIPS mode application crashes when AES encryption 
algorithm is used.
AES is FIPS compliant algorithms application should not crash when using AES.

application crashes from OpenSSL with message :
aes_misc.c(74): OpenSSL internal error, assertion failed: Low level API call to 
cipher AES forbidden in FIPS mode!

It can be seen in code for encryption and decryption, OpenSSL low level APIs 
are used. which gets blocked when OpenSSL is in FIPS mode.
Here is the code snippet from library(snmplib/scapi.c)

For Encryption:

int sc_encrypt () {
...
#ifdef HAVE_AES
    if (ISTRANSFORM(privtype, AESPriv)) {
        (void) AES_set_encrypt_key(key, properlength*8, &aes_key);
        memcpy(my_iv, iv, ivlen);
        /*
         * encrypt the data
         */
        AES_cfb128_encrypt(plaintext, ciphertext, ptlen,
                           &aes_key, my_iv, &new_ivlen, AES_ENCRYPT);
        *ctlen = ptlen;
    }
#endif
...
}

For Decryption:

int sc_decrypt() {
...
#ifdef HAVE_AES
    if (ISTRANSFORM(privtype, AESPriv)) {
        (void) AES_set_encrypt_key(key, properlength*8, &aes_key);
        memcpy(my_iv, iv, ivlen);
        /*
         * encrypt the data
         */
        AES_cfb128_encrypt(ciphertext, plaintext, ctlen,
                           &aes_key, my_iv, &new_ivlen, AES_DECRYPT);
        *ptlen = ctlen;
    }
#endif
...
}


OpenSSL api AES_set_encrypt_key() is blocked from openssl  if it runs in FIPS 
mode.

I have tried modifying the above code to use Openssl EVP apis instead of low 
level apis for encryption and decryption for AES.
Below are the changes:

For Encryption:

int sc_encrypt() {
...

#ifdef HAVE_AES
    if (ISTRANSFORM(privtype, AESPriv))
   {
      EVP_CIPHER_CTX ctx;
      int outlen = 0;
      int tmplen = 0;

      EVP_CIPHER_CTX_init(&ctx);

      EVP_EncryptInit_ex(&ctx, EVP_aes_128_cfb(), NULL, key, iv);

      EVP_CIPHER_CTX_set_key_length(&ctx, keylen);

      if(!EVP_EncryptUpdate(&ctx, ciphertext, &outlen, plaintext, ptlen))
      {
         snmp_log(LOG_ERR, "Cipher encryption update of plaintext failed\n");
         return FALSE;
      }

      /* Buffer passed to EVP_EncryptFinal() must be after data just
       * encrypted to avoid overwriting it.
       */
      if(!EVP_EncryptFinal_ex(&ctx, ciphertext + outlen, &tmplen))
      {
         snmp_log(LOG_ERR, "Final cipher encryption of plaintext failed\n");
         return FALSE;
      }

      outlen += tmplen;

      EVP_CIPHER_CTX_cleanup(&ctx);
      *ctlen = outlen;
    }
#endif
...
}

For Decryption:

int sc_decrypt(){
...

#ifdef HAVE_AES
    if (ISTRANSFORM(privtype, AESPriv)) {

      int decryptedLength = 0;
      int lastDecryptLength = 0;

      EVP_CIPHER_CTX cryptCtx;

      // Initialization
      EVP_CIPHER_CTX_init(&cryptCtx);

      if (EVP_DecryptInit_ex(&cryptCtx, EVP_aes_128_cfb(), NULL, key, iv) == 1)
      {
         EVP_CIPHER_CTX_set_key_length(&cryptCtx, keylen);

         /* Note that EVP_DecryptUpdate will alter the value of the third 
parameter to be equal to the amount of data that was written. */
         /* This is not always the entire length of the decrypted data! To 
finish the decryption process, use EVP_DecryptFinal_ex.      */
         /* This will decrypt any remaining data */
         if (EVP_DecryptUpdate(&cryptCtx, plaintext, &decryptedLength, 
ciphertext, ctlen) == 1)
         {
             // Stick the final data at the end of the last
             // decrypted data.

            if(EVP_DecryptFinal_ex(&cryptCtx, plaintext + decryptedLength, 
&lastDecryptLength) == 1)
            {
                decryptedLength = decryptedLength + lastDecryptLength;
                plaintext[decryptedLength] = 0;
            }
           else
            {
               snmp_log(LOG_ERR, "EVP_DecryptFinal_ex final decryption 
failed.\n");
               return FALSE;
            }
         }
         else
         {
               snmp_log(LOG_ERR, "EVP_DecryptUpdate update decryption 
failed.\n");
               return FALSE;
         }
      }
      else
      {
            snmp_log(LOG_ERR,"EVP_DecryptInit_ex init decryption failed.\n");
            return FALSE;
      }
    }
#endif
...
}

With these changes, application works without any problem.
Kindly let me know if the above scenario is considered as issues and will be 
fixed in library.
Please provide comments and let me know if any patch addressing the issue will 
be released.


Thanks & Regards,
Pushpendra
------------------------------------------------------------------------------
_______________________________________________
Net-snmp-coders mailing list
Net-snmp-coders@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/net-snmp-coders

Reply via email to