~myers-1/pyopenssl/npn

« back to all changes in this revision

Viewing changes to src/crypto/crypto.c

  • Committer: James Yonan
  • Date: 2010-02-27 12:45:50 UTC
  • mto: This revision was merged to the branch mainline in revision 130.
  • Revision ID: james@openvpn.net-20100227124550-2w4covlwb2ebs1pv
* src/crypto/crypto.c: Added crypto.sign and crypto.verify methods
  that wrap EVP_Sign and EVP_Verify function families, using code
  derived from Dave Cridland's PyOpenSSL branch.

* test/test_crypto.py: Added unit tests for crypto.sign and
  crypto.verify.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 * crypto.c
3
3
 *
4
4
 * Copyright (C) AB Strakt 2001, All rights reserved
 
5
 * Copyright (C) Keyphrene 2004, All rights reserved
5
6
 * Copyright (C) Jean-Paul Calderone 2008-2009, All rights reserved
6
7
 *
7
8
 * Main file of crypto sub module.
545
546
    return NULL;
546
547
}
547
548
 
 
549
static char crypto_sign_doc[] = "\n\
 
550
Sign data with a digest\n\
 
551
\n\
 
552
@param pkey: Pkey to sign with\n\
 
553
@param data: data to be signed\n\
 
554
@param digest: message digest to use\n\
 
555
@return: signature\n\
 
556
";
 
557
 
 
558
static PyObject *
 
559
crypto_sign(PyObject *spam, PyObject *args)
 
560
{
 
561
  PyObject *buffer;
 
562
  crypto_PKeyObj *pkey;
 
563
  char *data = NULL;
 
564
  char *digest_name;
 
565
  int err;
 
566
  unsigned int sig_len;
 
567
  const EVP_MD *digest;
 
568
  EVP_MD_CTX md_ctx;
 
569
  unsigned char sig_buf[512];
 
570
 
 
571
  if (!PyArg_ParseTuple(args, "O!ss:sign", &crypto_PKey_Type,
 
572
                        &pkey, &data, &digest_name))
 
573
    return NULL;
 
574
 
 
575
  if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
 
576
    {
 
577
      PyErr_SetString(PyExc_ValueError, "No such digest method");
 
578
      return NULL;
 
579
    }
 
580
 
 
581
  EVP_SignInit (&md_ctx, digest);
 
582
  EVP_SignUpdate (&md_ctx, data, strlen(data));
 
583
  sig_len = sizeof(sig_buf);
 
584
  err = EVP_SignFinal (&md_ctx, sig_buf, &sig_len, pkey->pkey);
 
585
 
 
586
  if (err != 1) {
 
587
    exception_from_error_queue(crypto_Error);
 
588
    return NULL;
 
589
  }
 
590
 
 
591
  buffer = PyString_FromStringAndSize(sig_buf, sig_len);
 
592
  return buffer;
 
593
}
 
594
 
 
595
static char crypto_verify_doc[] = "\n\
 
596
Verify a signature\n\
 
597
\n\
 
598
@param cert: signing certificate (X509 object)\n\
 
599
@param signature: signature returned by sign function\n\
 
600
@param data: data to be verified\n\
 
601
@param digest: message digest to use\n\
 
602
@return: None if the signature is correct, raise exception otherwise\n\
 
603
";
 
604
 
 
605
static PyObject *
 
606
crypto_verify(PyObject *spam, PyObject *args)
 
607
{
 
608
  crypto_X509Obj *cert;
 
609
  unsigned char *signature;
 
610
  int sig_len;
 
611
  char *data, *digest_name;
 
612
  int err;
 
613
  const EVP_MD *digest;
 
614
  EVP_MD_CTX md_ctx;
 
615
  EVP_PKEY *pkey;
 
616
 
 
617
  if (!PyArg_ParseTuple(args, "O!t#ss:verify", &crypto_X509_Type, &cert, &signature, &sig_len,
 
618
                        &data, &digest_name))
 
619
    return NULL;
 
620
 
 
621
  if ((digest = EVP_get_digestbyname(digest_name)) == NULL){
 
622
    PyErr_SetString(PyExc_ValueError, "No such digest method");
 
623
    return NULL;
 
624
  }
 
625
  pkey=X509_get_pubkey(cert->x509);
 
626
  if (pkey == NULL) {
 
627
    PyErr_SetString(PyExc_ValueError, "No public key");
 
628
    return NULL;
 
629
  }
 
630
 
 
631
  EVP_VerifyInit (&md_ctx, digest);
 
632
  EVP_VerifyUpdate (&md_ctx, data, strlen((char*)data));
 
633
  err = EVP_VerifyFinal (&md_ctx, signature, sig_len, pkey);
 
634
  EVP_PKEY_free (pkey);
 
635
 
 
636
  if (err != 1) {
 
637
    exception_from_error_queue(crypto_Error);
 
638
    return NULL;
 
639
  }
 
640
 
 
641
  Py_INCREF(Py_None);
 
642
  return Py_None;
 
643
}
548
644
 
549
645
/* Methods in the OpenSSL.crypto module (i.e. none) */
550
646
static PyMethodDef crypto_methods[] = {
557
653
    { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
558
654
    { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
559
655
    { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
 
656
    { "sign", (PyCFunction)crypto_sign, METH_VARARGS, crypto_sign_doc },
 
657
    { "verify", (PyCFunction)crypto_verify, METH_VARARGS, crypto_verify_doc },
560
658
    { "X509_verify_cert_error_string", (PyCFunction)crypto_X509_verify_cert_error_string, METH_VARARGS, crypto_X509_verify_cert_error_string_doc },
561
659
    { "_exception_from_error_queue", (PyCFunction)crypto_exception_from_error_queue, METH_NOARGS, crypto_exception_from_error_queue_doc },
562
660
    { NULL, NULL }