zxid

 view release on metacpan or  search on metacpan

zxcrypto.c  view on Meta::CPAN

  case RSA_PKCS1_PADDING:
  case RSA_SSLV23_PADDING:
    if (plain->len > (siz-11))
      ERR("Too much data for RSA key: can=%d, you have %d bytes.\n", siz-11, plain->len);
    WARN("RSA_PKCS1_PADDING %d v1.5: WARNING: This padding is vulnearable to attacks. Use OAEP instead.", pad);
    /* See paper: Tibor Jager, Kenneth G. Paterson, Juraj Somorovsky: "One Bad Apple: Backwards Compatibility Attacks on State-of-the-Art Cryptography", 2013 http://www.nds.ruhr-uni-bochum.de/research/publications/backwards-compatibility/ /t/Backward...
    break;
  case RSA_NO_PADDING:
    if (plain->len > siz)
      ERR("Too much data for RSA key: can=%d, you have %d bytes.\n", siz, plain->len);
    break;
  case RSA_PKCS1_OAEP_PADDING:
    if (plain->len > (siz-41))
      ERR("Too much data for RSA key: can=%d, you have %d bytes.\n", siz-41, plain->len);
    break;
  default: D("Illegal padding(%d). See `man 3 rsa'\n",pad);
  }

  ciphered = zx_new_len_str(c, siz);
  if (!ciphered)
    return 0;
  ret = RSA_public_encrypt(plain->len, (unsigned char*)plain->s, (unsigned char*)ciphered->s, rsa_pkey, pad);
  if (siz != ret) {
    D("RSA pub enc wrong ret=%d siz=%d\n",ret,siz);
    zx_report_openssl_err("zx_pub_encrypt_rsa fail (${ret})");
    return 0;
  }
  ASSERTOPI(ret, <=, siz);
  ciphered->len = ret;
  ciphered->s[ret] = 0;
  return ciphered;
}

/*() RSA public key decryption. See zx_get_rsa_pub_from_cert() for
 * a way to obtain public key data structure. */

/* Called by: */
struct zx_str* zx_rsa_pub_dec(struct zx_ctx* c, struct zx_str* ciphered, RSA* rsa_pkey, int pad)
{
  struct zx_str* plain;
  int ret, siz = RSA_size(rsa_pkey);
  plain = zx_new_len_str(c, siz);
  if (!plain)
    return 0;
  if ((errmac_debug&ERRMAC_DEBUG_MASK) > 2) {
    D("pad=%d, RSA public key follows...", pad);
    RSA_print_fp(ERRMAC_DEBUG_LOG, rsa_pkey, 0);
  }
  ret = RSA_public_decrypt(ciphered->len, (unsigned char*)ciphered->s, (unsigned char*)plain->s, rsa_pkey, pad);
  if (ret == -1) {
    D("RSA public decrypt failed ret=%d len_cipher_data=%d",ret,ciphered->len);
    zx_report_openssl_err("zx_public_decrypt_rsa fail");
    return 0;
  }
  ASSERTOPI(ret, <=, siz);
  plain->len = ret;
  plain->s[ret] = 0;
  return plain;
}

/*() RSA private key decryption. See zxid_read_private_key() and zxid_extract_private_key()
 * for ways to read in the private key data structure.
 * N.B. This function +only+ does the private key part. It does not
 * perform combined dec-session-key-with-priv-key-and-then-data-with-session-key
 * operation, though this function could be used as a component to implement
 * such a system.
 *
 * This is considered a low level function. See zxenc_privkey_dec() for a higher level solution. */

/* Called by:  zxenc_privkey_dec x2 */
struct zx_str* zx_rsa_priv_dec(struct zx_ctx* c, struct zx_str* ciphered, RSA* rsa_pkey, int pad)
{
  struct zx_str* plain;
  int ret, siz = RSA_size(rsa_pkey);
  plain = zx_new_len_str(c, siz);
  if (!plain)
    return 0;
  if ((errmac_debug&ERRMAC_DEBUG_MASK) > 2) {
    D("pad=%d, RSA private key follows...", pad);
    RSA_print_fp(ERRMAC_DEBUG_LOG, rsa_pkey, 0);
  }
  ret = RSA_private_decrypt(ciphered->len, (unsigned char*)ciphered->s, (unsigned char*)plain->s, rsa_pkey, pad);
  if (ret == -1) {
    D("RSA private decrypt failed ret=%d len_cipher_data=%d",ret,ciphered->len);
    zx_report_openssl_err("zx_priv_decrypt_rsa fail");
    return 0;
  }
  ASSERTOPI(ret, <=, siz);
  plain->len = ret;
  plain->s[ret] = 0;
  return plain;
}

/*() RSA private key encryption. See zxid_read_private_key() and zxid_extract_private_key()
 * for ways to read in the private key data structure. */

/* Called by: */
struct zx_str* zx_rsa_priv_enc(struct zx_ctx* c, struct zx_str* plain, RSA* rsa_pkey, int pad)
{
  struct zx_str* ciphered;
  int ret, siz = RSA_size(rsa_pkey);
  ciphered = zx_new_len_str(c, siz);
  if (!ciphered)
    return 0;
  if ((errmac_debug&ERRMAC_DEBUG_MASK) > 2) {
    D("pad=%d, RSA private key follows...", pad);
    RSA_print_fp(ERRMAC_DEBUG_LOG, rsa_pkey, 0);
  }
  ret = RSA_private_encrypt(plain->len, (unsigned char*)plain->s, (unsigned char*)ciphered->s, rsa_pkey, pad);
  if (ret == -1) {
    D("RSA private encrypt failed ret=%d len_plain=%d", ret, plain->len);
    zx_report_openssl_err("zx_priv_encrypt_rsa fail");
    return 0;
  }
  ASSERTOPI(ret, <=, siz);
  ciphered->len = ret;
  ciphered->s[ret] = 0;
  return ciphered;
}

/*() Obtain RSA public key from X509 certificate. The certificate must have been
 * previously read into a data structure. See zxid_read_cert() and zxid_extract_cert() */

/* Called by:  zxenc_pubkey_enc, zxlog_write_line */
RSA* zx_get_rsa_pub_from_cert(X509* cert, char* logkey)
{
  EVP_PKEY* evp_pkey;
  struct rsa_st* rsa_pkey;
  evp_pkey = X509_get_pubkey(cert);
  if (!evp_pkey) {
    ERR("RSA enc: failed to get public key from certificate (perhaps you have not supplied any certificate, or it is corrupt or of wrong type) %s", logkey);
    zx_report_openssl_err("zx_get_rsa_pub_from_cert");
    return 0;
  }
  rsa_pkey = EVP_PKEY_get1_RSA(evp_pkey);
  if (!rsa_pkey) {
    ERR("RSA enc: failed to extract RSA get public key from certificate (perhaps you have not supplied any certificate, or it is corrupt or of wrong type) %s", logkey);
    zx_report_openssl_err("zx_get_rsa_pub_from_cert");
    return 0;
  }
  return rsa_pkey;
}

/*() ZXID centralized hook for obtaning random numbers. This backends to
 * OpenSSL random number gnerator and seeds from /dev/urandom where
 * available. If you want to use /dev/random, which may block, you need
 * to recompile with ZXID_TRUE_RAND set to true. */

/* Called by: */
void zx_rand(char* buf, int n_bytes)
{
#ifdef USE_OPENSSL
#if ZXID_TRUE_RAND
  RAND_bytes(buf, n_bytes);

zxcrypto.c  view on Meta::CPAN

  
  /* Set up V3 context struct and add certificate extensions. Note
   * that we need to add (full) suite of CA extensions, otherwise
   * our cert is not valid for signing itself. */
  
  ext = X509V3_EXT_conf_nid(0, 0, NID_basic_constraints, "CA:TRUE,pathlen:3");
  X509_add_ext(x509ss, ext, -1);
  
  ext = X509V3_EXT_conf_nid(0, 0, NID_netscape_cert_type, "client,server,email,objsign,sslCA,emailCA,objCA");
  X509_add_ext(x509ss, ext, -1);
  
  ext = X509V3_EXT_conf_nid(0, 0, NID_key_usage, "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign");
  X509_add_ext(x509ss, ext, -1);

  ext = X509V3_EXT_conf_nid(0, 0, NID_netscape_comment, "Auto-Cert, see zxid.org");
  X509_add_ext(x509ss, ext, -1);
  
  DD("keygen signing x509ss %s", lk);
#if 0
  if (!(X509_sign(x509ss, pkey, EVP_md5())))
#else
  if (!(X509_sign(x509ss, pkey, EVP_sha256())))
#endif
  {
    ERR("Failed to sign x509ss %s", lk);
    zx_report_openssl_err("X509_sign");
    return 0;
  }
  DD("keygen x509ss ready %s", lk);

  /* ----- Output phase ----- */

  um = umask(0077);  /* Key material should be readable only by owner */

  wbio_csr = BIO_new(BIO_s_mem());
  DD("write_csr %s", lk);
  if (!PEM_write_bio_X509_REQ(wbio_csr, req)) {
    ERR("write_csr %s", lk);
    zx_report_openssl_err("write_csr");
    return 0;
  }
  len = BIO_get_mem_data(wbio_csr, &p);

  write_all_path("auto_cert csr", "%s" ZXID_PEM_DIR "csr-%s", cf->cpath, name, len, p);
  BIO_free_all(wbio_csr);

  /* Output combined self signed plus private key file. It is important
   * that this happens after csr so that buf is left with this data
   * so that the caller can then parse it. */

  wbio_cert = BIO_new(BIO_s_mem());
  DD("write_cert %s", lk);
  if (!PEM_write_bio_X509(wbio_cert, x509ss)) {
    ERR("write_cert %s", lk);
    zx_report_openssl_err("write_cert");
    return 0;
  }
  len = BIO_get_mem_data(wbio_cert, &p);

  wbio_pkey = BIO_new(BIO_s_mem());
  DD("write_private_key %s", lk);
  if (!PEM_write_bio_PrivateKey(wbio_pkey, pkey, 0,0,0,0,0)) {
    ERR("write_private_key %s", lk);
    zx_report_openssl_err("write_private_key");
    return 0;
  }
  lenq = BIO_get_mem_data(wbio_pkey, &q);

  write_all_path_fmt("auto_cert ss", buflen, buf,
		     "%s" ZXID_PEM_DIR "%s", cf->cpath, name,
		     "%.*s%.*s", len, p, lenq, q);

  BIO_free_all(wbio_cert);
  BIO_free_all(wbio_pkey);

  umask(um);

  EVP_PKEY_free(pkey);
  X509_REQ_free(req);
  X509_free(x509ss);
  X509V3_EXT_cleanup();
  OBJ_cleanup();

  zxlog(cf, 0, 0, 0, 0, 0, 0, 0, 0, "K", "KEYGEN", name, 0);
  D("keygen done. %s", lk);
  return 1;
#else
  ERR("ZXID was compiled without USE_OPENSSL. This means self signed certificate generation facility is unavailable. Recompile ZXID. %s", lk);
  return 0;
#endif
}

#if 0
/* use PEM_write_X509(fp, cert) instead! */
/* Called by: */
void zx_print_X509(FILE* fp, X509* cert)
{
  int len;
  char* p;
  BIO* wbio_cert = BIO_new(BIO_s_mem());
  if (!PEM_write_bio_X509(wbio_cert, peer_cert)) {
    ERR("write_cert %p", peer_cert);
    zx_report_openssl_err("write_cert");
    return;
  }
  len = BIO_get_mem_data(wbio_cert, &p);
  fprintf(fp, "%.*s", len, p);
}
#endif

/*

A Practical Approach of X.509 Attribute Certificate Framework as Support to Obtain Privilege Delegation
Jose A. Montenegro and Fernando Moya
Computer Science Department, E.T.S. Ingenieria Informatica, Universidad de Malage, Spain
Lecture Notes in Computer Science, 2004, Volume 3093/2004, 624, DOI: 10.1007/978-3-540-25980-0_13 

 Abstract This work introduces a particular implementation of the
X.509 Attribute Certificate framework (Xac), presented in the ITU-T
Recommendation. The implementation is based on the use of the Openssl
library, that we have chosen for its advantages in comparison with
other libraries. The paper also describes how the implementation is
middleware-oriented, focusing on the delegation model specified by
ITU-T proposal, and taking into consideration the ETSI report about



( run in 0.943 second using v1.01-cache-2.11-cpan-39bf76dae61 )