Main Content

Missing public key

Context used for cryptography operation is associated with NULL public key or not associated with a public key at all

Description

This defect occurs when you use a context object for encryption or signature authentication but you have not previously associated the object with a non-NULL public key.

For instance, you initialize the context object with a NULL public key and use the object for encryption later.

ctx = EVP_PKEY_CTX_new(pkey, NULL);
...
ret = EVP_PKEY_encrypt_init(ctx);
...
ret = EVP_PKEY_encrypt(ctx, out, &out_len, in, in_len);

The counterpart checker Missing private key checks for a private key in decryption and signature operations.

Risk

Without a public key, the encryption or signature authentication step does not happen. The redundant operation often indicates a coding error.

Fix

Check the placement of the operation (encryption or signature authentication). If the operation is intended to happen, make sure you have done these steps prior to the operation:

  • You generated a non-NULL public key.

    For instance:

    EVP_PKEY *pkey = NULL;
    kctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
    
    EVP_PKEY_keygen_init(kctx);
    EVP_PKEY_CTX_set_rsa_keygen_bits(kctx, RSA_2048BITS);
    EVP_PKEY_keygen(kctx, &pkey);

  • You associated a non-NULL context object with the public key.

    For instance:

    ctx = EVP_PKEY_CTX_new(pkey, NULL);
    

    Note: If you use EVP_PKEY_CTX_new_id instead of EVP_PKEY_CTX_new, you are not associating the context object with a public key.

Examples

expand all

#include <stddef.h>
#include <openssl/evp.h>

#define fatal_error() exit(-1)

int ret;
unsigned char *out_buf;
size_t out_len;

int func(unsigned char *src, size_t len){
  EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
  if (ctx == NULL) fatal_error();

  ret = EVP_PKEY_encrypt_init(ctx);
  if (ret <= 0) fatal_error();
  return EVP_PKEY_encrypt(ctx, out_buf, &out_len, src, len); 
}

In this example, the context object ctx is initialized with EVP_PKEY_CTX_new_id instead of EVP_PKEY_CTX_new. The function EVP_PKEY_CTX_new_id does not associate the context object with a key. However, the EVP_PKEY_encrypt function uses this object for decryption.

Correction — Associate Public Key with Context During Initialization

One possible correction is to use the EVP_PKEY_CTX_new function for context initialization and associate a public key with the context object. In the following correction, the public key pkey is obtained from an external source and checked for NULL before use.

#include <stddef.h>
#include <openssl/evp.h>

#define fatal_error() exit(-1)

int ret;
unsigned char *out_buf;
size_t out_len;

int func(unsigned char *src, size_t len, EVP_PKEY *pkey){
  if (pkey == NULL) fatal_error(); 
  
  EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
  if (ctx == NULL) fatal_error();

  ret = EVP_PKEY_encrypt_init(ctx);
  if (ret <= 0) fatal_error();
  return EVP_PKEY_encrypt(ctx, out_buf, &out_len, src, len); 
}

Result Information

Group: Cryptography
Language: C | C++
Default: Off
Command-Line Syntax: CRYPTO_PKEY_NO_PUBLIC_KEY
Impact: Medium

Version History

Introduced in R2018a