Ejemplo n.º 1
0
PKI_MEM *PKI_MEM_new_func ( void *obj, int (*func)(void *, unsigned char **p)) {

	size_t size = 0;
	int i = 0;
	PKI_MEM * ret = NULL;

	if (!obj || !func ) return NULL;

	if((i =  func ( obj, NULL)) <= 0 ) {
		return NULL;
	}

	size = (size_t) i;

	if((ret = PKI_MEM_new ( size )) == NULL ) {
		return NULL;
	}

	if ( !func(obj, &(ret->data)) ) {
		PKI_MEM_free ( ret );
		return NULL;
	}

	return ret;
}
Ejemplo n.º 2
0
PKI_MEM * HSM_OPENSSL_sign(PKI_MEM *der, PKI_DIGEST_ALG *digest, PKI_X509_KEYPAIR *key)
{

	EVP_MD_CTX *ctx = NULL;
	size_t out_size = 0;
	size_t ossl_ret = 0;

	PKI_MEM *out_mem = NULL;
	EVP_PKEY *pkey = NULL;

	if (!der || !der->data || !key || !key->value)
	{
		PKI_ERROR( PKI_ERR_PARAM_NULL, NULL);
		return NULL;
	}

	// Private Key
	pkey = key->value;

	// Get the Maximum size of a signature
	ossl_ret = out_size = (size_t) EVP_PKEY_size(pkey);

	// Initialize the return structure
	out_mem = PKI_MEM_new ((size_t)out_size);
	ctx = EVP_MD_CTX_new();

	if (!out_mem || !ctx) {
		if (ctx) EVP_MD_CTX_free(ctx);
		if (out_mem) PKI_MEM_free(out_mem);
		PKI_ERROR( PKI_ERR_MEMORY_ALLOC, NULL);
		return NULL;
	}

	EVP_MD_CTX_init(ctx);
	EVP_SignInit_ex(ctx, digest, NULL);
	EVP_SignUpdate (ctx, der->data, der->size);

	// Finalize the signature
	if (!EVP_SignFinal(ctx, out_mem->data, (unsigned int *) &ossl_ret, pkey))
	{
		PKI_log_err("ERROR while finalizing signature (%s)", 
			HSM_OPENSSL_get_errdesc(HSM_OPENSSL_get_errno(), NULL, 0));

		PKI_MEM_free(out_mem);
		out_mem = NULL;
	}
	else out_mem->size = (size_t) ossl_ret;

	// Cleanup the context
#if OPENSSL_VERSION_NUMBER <= 0x1010000f
	EVP_MD_CTX_cleanup(ctx);
#else
	EVP_MD_CTX_reset(ctx);
#endif
	EVP_MD_CTX_free(ctx);

	return out_mem;
}
Ejemplo n.º 3
0
PKI_MEM *PKI_MEM_new_data ( size_t size, unsigned char *data ) {

	PKI_MEM *ret = NULL;

	if( !data || size == 0 ) return ( NULL );

	if((ret = PKI_MEM_new ( size )) == NULL ) {
		return ( NULL );
	}

	memcpy(ret->data, data, size);

	return ( ret );
}
Ejemplo n.º 4
0
int PKI_HMAC_finalize(PKI_HMAC *hmac)
{
	int size = 0;
	unsigned int verify_size = 0;

	if (!hmac || !hmac->initialized)
		return PKI_ERROR(PKI_ERR_PARAM_NULL, NULL);

	// Let's prepare the return value
	size = EVP_MD_size(hmac->digestAlg);
	verify_size = (unsigned int) size;

	// Generate a new PKI_MEM container
	hmac->value = PKI_MEM_new((size_t) size);

	// Let's finalize the HMAC
#if OPENSSL_VERSION_NUMBER > 0x0090900fL
	int rv = HMAC_Final(&hmac->ctx, hmac->value->data, &verify_size);
	if (!rv)
	{
		PKI_log_err("can not finalize HMAC");
		PKI_MEM_free(hmac->value);
		hmac->value = NULL;

		return PKI_ERR;
	}
#else
	// In OpenSSL < 0.9.9 the return value is actually void
	HMAC_Final(&hmac->ctx, hmac->value->data, &verify_size);
#endif

	// Checks the sizes
	if (verify_size != size)
	{
		PKI_log_err("Error while finalizing HMAC, size (%d) should be (%d)",
			verify_size, hmac->value->size);

		PKI_MEM_free(hmac->value);
		hmac->value = NULL;

		return PKI_ERR;
	}

	return PKI_OK;
}
Ejemplo n.º 5
0
PKI_HTTP *PKI_HTTP_get_message (const PKI_SOCKET * sock,
		                        int                timeout,
								size_t             max_size) {

  PKI_HTTP * ret = NULL;

  char * eoh = NULL;
  char * body = NULL;

  ssize_t read = 0; // Keeps track of the single reading
  ssize_t free = 0; // Keeps track of the remaining buffer space
  ssize_t idx = 0; // Keeps track of how much data we poured into MEM
  ssize_t size = 0; // Keeps track of the read data from socket

  // Let's initialize some useful variables (code readability)
  long long content_length = -1;

  // Buffer where to keep the data
  PKI_MEM *m = NULL;

  // Allocates the HTTP message container
  if ((ret = PKI_HTTP_new()) == NULL)
  {
      PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL );
      goto err;
  }
  ret->method = PKI_HTTP_METHOD_UNKNOWN;

  if (max_size > 0)
  {
	  // Allocates a new MEM object
	  m = PKI_MEM_new(max_size + 1);
  }
  else
  {
	  // Allocates the default buffer for HTTP messages
	  m = PKI_MEM_new(HTTP_BUF_SIZE + 1);
  }

	if (m == NULL)
	{
		PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL);
		return NULL;
	}

	// Sets the free space in the buffer
	free = (ssize_t) m->size - 1;

  // Let's retrieve the data from the socket. Note that this for
  // always read at most 'free' bytes which carries the amount of
  // free space in the buffer -> safe
  for (read = PKI_SOCKET_read(sock, (char *)(&(m->data[idx])), (size_t) free, timeout);
       read > 0;
       read = PKI_SOCKET_read(sock, (char *)(&(m->data[idx])), (size_t) free, timeout))
  {
      // If read is negative, there was an error on the socket
      // let's just report it as an error and move on
      if (read < 0)
      {
    	  if (!eoh)
    	  {
    		  PKI_log_err("Error while reading from socket");
    		  goto err;
    	  }
    	  else
    	  {
    		  // Nothing to read anymore - let's break
    		  PKI_log_err("Nothing to read anymore (read = %d)", read);
    		  break;
    	  }
      }
      else if (read == 0 && eoh)
      {
    	  // No data was read, let's assume the stream is complete and
    	  // break from the for loop
    	  break;
      }

      // Let's be sure there is a NULL-bound limit to the read data
      size += read;
      free -= read;
      m->data[size] = '\x0';

      // If we don't have a header yet, let's look for it
      if (!eoh && ((eoh = __find_end_of_header(m, idx)) != NULL))
      {
    	  // We want the header to finish with just one '\r\n' - since the
    	  // pointer we receive is at the end of the '\r\n\r\n' sequence,
    	  // we need to shrink by 2 bytes
    	  size_t header_size = (size_t) (eoh - (char *) m->data - 2);
    	  ret->head = PKI_MEM_new_data(header_size + 1, m->data);
    	  ret->head->data[header_size] = '\x0';

    	  // If we can not parse the header - we have to return error
    	  if (PKI_ERR == __parse_http_header(ret)) goto err;

    	  // Let's get the pointer to the start of the body
    	  body = eoh + 1;

    	  // Checks for the content-length is in the header - if we have not found it, yet
    	  if (ret->method != PKI_HTTP_METHOD_GET && content_length < 0)
    	  {
    		  char *cnt_len_s = NULL;
    		  if ((cnt_len_s = PKI_HTTP_get_header(ret, "Content-Length" )) != NULL)
    		  {
    			  content_length = atoll(cnt_len_s);
    			  PKI_Free(cnt_len_s);
    			  // PKI_log_debug ( "HTTP Content-Length: %d bytes", content_length);
    		  }
    	  }
      } // End of if (!eoh) ...

      // Updates the start pointer for the next read operation
      idx += read;

      // Let's check if we need to expand the buffer
      if (max_size <= 0)
      {
    	  // We expand the mem if the buffer has less than 2K free
    	  if (free < 2048)
    	  {
    			ssize_t ofs = 0;

    		  if(body)
    		  {
    		    ofs = (ssize_t)(body - (char *)m->data);
          
    		    if(ofs < 0)
    		    {
    		      PKI_log_debug ( "Invalid offset for HTTP body: Start: %p - Body: %p", m->data, body);
    		      PKI_ERROR(PKI_ERR_URI_READ, NULL);
    		      goto err;
    		    }
    		  }

    		  // Grow the memory for the HTTP message
    		  if(content_length > 0 && body && m->size < (size_t)(content_length + ofs))
    		  {
           size_t len = ((size_t)(content_length + ofs) - m->size);

    		    if (PKI_MEM_grow(m, len + 1) == PKI_ERR)
    		    {
    		      PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL);
    		      goto err;
    		    }
    		    free += (ssize_t)len;
    		  }
    		  else
    		  {
    		    if (PKI_MEM_grow(m, HTTP_BUF_SIZE) == PKI_ERR)
    		    {
    		      PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL);
    		      goto err;
    		    }
    		    free += HTTP_BUF_SIZE;
    		  }

    		  // Let's update the pointer to the body
    		  if(body) body = (char *)m->data + ofs;
    	  }
      }

      // Let's check if we need to perform the next read or not
      if (eoh && ret->method == PKI_HTTP_METHOD_GET)
      {
    	  // We do not need to wait for any other read as GETs do not have
    	  // a full body
    	  break;
      }
      else if ((content_length >= 0) && (&m->data[size] - (unsigned char *)body >= content_length))
      {
    	  // Here we have received the full body (since the size of the body corresponds or exceeds the
    	  // contents of the Content-Length: header line), therefore we can safely get out of the cycle
    	  break;
      }

  } /* End of for..loop */

  // Here we should have both the eoh and the body - if not, there was
  // an error and we return the malformed request message
  if (!eoh)
  {
	  // PKI_log_err ( "Read data (so far): %d bytes - Last read: %d bytes", idx, read);
	  PKI_ERROR(PKI_ERR_URI_READ, NULL);
	  goto err;
  }

  // Sets some HTTP specific data
  ret->location = PKI_HTTP_get_header ( ret, "Location" );
  ret->type     = PKI_HTTP_get_header ( ret, "Content-Type" );

  if (ret->method != PKI_HTTP_METHOD_GET && content_length > 0 && body)
  {
	  ssize_t body_start = (ssize_t)(body - (char *)m->data);
	  ssize_t body_size = idx - body_start;

	  if (body_start < 0 || body_size < 0)
	  {
		  PKI_log_err ( "Invalid offset for HTTP body - body_start: %d bytes - body_size: %d bytes", body_start, body_size);
		  PKI_ERROR(PKI_ERR_URI_READ, NULL);
		  goto err;
	  }
 
	  //Check if Content-Length > 0 but body_size is 0
	  if (body_size == 0) goto err; 

	  // Let's allocate the body for the HTTP message (if any)
	  ret->body = PKI_MEM_new_data((size_t)body_size+1, (unsigned char *)body);
	  if(ret->body == NULL)
	  {
		PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL);
		goto err;
	  }
	  ret->body->size = (size_t) body_size;
  }
  else
  {
	  ret->body = PKI_MEM_new_null();
  }

  // Let's free the buffer memory
  if (m) PKI_MEM_free(m);

  // Now we can return the HTTP message
  return ret;

err:

	// First we free the return message
	if (ret) PKI_HTTP_free(ret);

	// We then free the buffer memory object
	if (m) PKI_MEM_free(m);

	return NULL;
}