eater 2 years ago
parent
commit
31a5b24ded
Signed by: eater GPG Key ID: AD2560A0F84F0759
  1. 3
      resources/pkcs7.h
  2. 8
      resources/x509.h
  3. 7
      src/OpenSSL.php
  4. 5
      src/OpenSSL/C/CBackedObject.php
  5. 3
      src/OpenSSL/C/CBackedObjectWithOwner.php
  6. 4
      src/OpenSSL/PKCS7.php
  7. 23
      src/OpenSSL/PKCS7/Helpers.php
  8. 27
      src/OpenSSL/PKCS7/Signed.php
  9. 9
      src/OpenSSL/PKCS7/SignerInfo.php
  10. 16
      src/OpenSSL/PKCS7/Stack/SignerInfoStack.php
  11. 12
      src/OpenSSL/Stack.php
  12. 11
      src/OpenSSL/Stack/X509Stack.php
  13. 12
      src/OpenSSL/X509.php
  14. 16
      tests/PKCS7Test.php
  15. 12
      tests/StackTest.php

3
resources/pkcs7.h

@ -58,11 +58,8 @@ typedef struct pkcs7_signedandenveloped_st {
ASN1_INTEGER *version;
struct stack_st_X509_ALGOR *md_algs;
struct stack_st_X509 *cert;
struct stack_st_X509_CRL *crl;
struct stack_st_PKCS7_SIGNER_INFO *signer_info;
PKCS7_ENC_CONTENT *enc_data;

8
resources/x509.h

@ -235,7 +235,13 @@ struct stack_st_X509_CRL {
};
X509 *X509_new(void);
X509 *X509_dup(X509 *x509);
void X509_free(X509 *a);
X509_STORE *X509_STORE_new(void);
void X509_STORE_free(X509_STORE *v);
void X509_STORE_free(X509_STORE *v);
X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void);
X509_LOOKUP_METHOD *X509_LOOKUP_file(void);
int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type);

7
src/OpenSSL.php

@ -66,4 +66,11 @@ class OpenSSL
{
return FFI::cast("long long", $data)->cdata;
}
static $caStore = null;
public static function CAStore()
{
}
}

5
src/OpenSSL/C/CBackedObject.php

@ -94,4 +94,9 @@ class CBackedObject
{
$this->managed = true;
}
public function getCData(): CData
{
return $this->cObj;
}
}

3
src/OpenSSL/C/CBackedObjectWithOwner.php

@ -3,6 +3,7 @@
namespace Cijber\OpenSSL\C;
use Cijber\OpenSSL;
use Cijber\OpenSSL\FFIWrapper;
use FFI;
use FFI\CData;
@ -43,7 +44,7 @@ class CBackedObjectWithOwner extends CBackedObject
* Cast first, so it acts like a pointer
*/
$casted = $ffi->cast(static::TYPE, $cData);
$address = FFI::cast("long long", $casted)->cdata;
$address = OpenSSL::addressOf($casted);
if (array_key_exists($address, static::$known)) {
return static::$known[$address];
}

4
src/OpenSSL/PKCS7.php

@ -32,7 +32,7 @@ class PKCS7 extends OpenSSL\C\CBackedObjectWithOwner
return $this->ffi->OBJ_obj2nid($this->cObj->type);
}
public function toSigned(): PKCS7\Signed
public function asSigned(): PKCS7\Signed
{
$this->ensureNotFreed();
@ -40,7 +40,7 @@ class PKCS7 extends OpenSSL\C\CBackedObjectWithOwner
throw new RuntimeException("This PKCS7 isn't of type signed");
}
return new PKCS7\Signed($this);
return PKCS7\Signed::fromPKCS7($this, $this->ffi, $this->cObj->d->sign, $this->cObj);
}
/**

23
src/OpenSSL/PKCS7/Helpers.php

@ -4,10 +4,28 @@
namespace Cijber\OpenSSL\PKCS7;
use Cijber\OpenSSL\PKCS7;
use FFI;
use FFI\CData;
trait Helpers
{
protected PKCS7 $pkcs7;
protected CData $data;
protected CData $parent;
protected FFI $ffi;
public function __construct(PKCS7 $pkcs7, FFI $ffi, CData $data, CData $parent)
{
$this->pkcs7 = $pkcs7;
$this->ffi = $ffi;
$this->data = $data;
$this->parent = $parent;
}
public static function fromPKCS7(PKCS7 $param, FFI $ffi, CData $data, CData $parent)
{
return new static($param, $ffi, $data, $parent);
}
public function toDER(): string
{
@ -21,9 +39,4 @@ trait Helpers
{
return $this->pkcs7;
}
public function __construct(PKCS7 $pkcs7)
{
$this->pkcs7 = $pkcs7;
}
}

27
src/OpenSSL/PKCS7/Signed.php

@ -3,11 +3,36 @@
namespace Cijber\OpenSSL\PKCS7;
use Cijber\OpenSSL;
use Cijber\OpenSSL\BIO;
use Cijber\OpenSSL\PKCS7;
use Cijber\OpenSSL\Stack\X509Stack;
use Cijber\OpenSSL\X509Store;
use FFI;
use FFI\CData;
class Signed
{
use Helpers;
public function getSigners()
public function getCerts(): X509Stack
{
$stack = X509Stack::from($this->ffi, $this->data->cert, $this);
$stack->unmanaged();
return $stack;
}
public function verify(string $plain, ?X509Store $x509Store = null)
{
if ($x509Store === null) {
$x509Store = OpenSSL::CAStore();
}
$buffer = BIO::buffer($plain);
$x = $this->ffi->PKCS7_verify($this->parent, null, null, $buffer->getCData(), null, 0);
return $x === 1;
}
}

9
src/OpenSSL/PKCS7/SignerInfo.php

@ -0,0 +1,9 @@
<?php
namespace Cijber\OpenSSL\PKCS7;
class SignerInfo
{
const TYPE = "PKCS7_SIGNER_INFO*";
}

16
src/OpenSSL/PKCS7/Stack/SignerInfoStack.php

@ -0,0 +1,16 @@
<?php
namespace Cijber\OpenSSL\PKCS7\Stack;
use Cijber\OpenSSL\PKCS7\SignerInfo;
use Cijber\OpenSSL\Stack;
use FFI\CData;
class SignerInfoStack extends Stack
{
protected function spawn(CData $cData): SignerInfo
{
// TODO: Implement spawn() method.
}
}

12
src/OpenSSL/Stack.php

@ -8,6 +8,7 @@ use Cijber\OpenSSL;
use Cijber\OpenSSL\C\CBackedObject;
use Cijber\OpenSSL\C\CBackedObjectWithOwner;
use Countable;
use FFI;
use FFI\CData;
use InvalidArgumentException;
use IteratorAggregate;
@ -21,9 +22,18 @@ use Traversable;
abstract class Stack extends CBackedObjectWithOwner implements Countable, ArrayAccess, Traversable, IteratorAggregate
{
const CLASSNAME = CBackedObjectWithOwner::class;
const TYPE = "struct stack_st*";
abstract protected function spawn(CData $cData);
protected $owner;
protected function __construct(FFI $ffi, CData $cObj, $owner = null)
{
parent::__construct($ffi, $ffi->cast(self::TYPE, $cObj));
$this->owner = $owner;
}
public static function new()
{
$ffi = OpenSSL::getFFI();
@ -100,8 +110,6 @@ abstract class Stack extends CBackedObjectWithOwner implements Countable, ArrayA
throw new RuntimeException("Failed to insert element");
}
$object->pushRefCount();
return $idx;
}

11
src/OpenSSL/Stack/X509Stack.php

@ -12,13 +12,18 @@ class X509Stack extends Stack
{
const CLASSNAME = X509::class;
public static function from(FFI $ffi, CData $cObj): X509Stack
public static function from(FFI $ffi, CData $cObj, $owner = null): X509Stack
{
return new X509Stack($ffi, $cObj);
return new X509Stack($ffi, $cObj, $owner = null);
}
public function spawn(CData $cData): X509
{
return X509::cast($this->ffi, $cData);
$obj = $this->ffi->cast(X509::TYPE, $cData);
$clone = $this->ffi->X509_dup($obj);
if ($clone === null) {
return X509::new();
}
return X509::cast($this->ffi, $clone);
}
}

12
src/OpenSSL/X509.php

@ -5,6 +5,7 @@ namespace Cijber\OpenSSL;
use Cijber\OpenSSL;
use Cijber\OpenSSL\C\CBackedObjectWithOwner;
use FFI;
class X509 extends CBackedObjectWithOwner
{
@ -21,4 +22,15 @@ class X509 extends CBackedObjectWithOwner
{
$this->ffi->X509_free($this->cObj);
}
public function getName()
{
return FFI::string($this->cObj->name);
}
public function getSHA1Hash()
{
$hash = FFI::string($this->cObj->sha1_hash, 20);
return $hash;
}
}

16
tests/PKCS7Test.php

@ -3,6 +3,7 @@
namespace Cijber\OpenSSL\Tests;
use Cijber\OpenSSL\PKCS7;
use Cijber\OpenSSL\X509;
use PHPUnit\Framework\TestCase;
use RuntimeException;
@ -22,6 +23,21 @@ class PKCS7Test extends TestCase
$newDer = $pkcs7->toDER();
$this->assertEquals(PKCS7::NID_SIGNED, $pkcs7->getType());
$this->assertEquals($der, $newDer);
$signed = $pkcs7->asSigned();
$certs = $signed->getCerts();
$this->assertCount(1, $certs);
/** @var X509 $x509 */
$x509 = $certs[0];
$x = $x509->getName();
$this->assertEquals("/C=US/ST=New York/L=New York/OU=FDroid Repo/O=Guardian Project/CN=guardianproject.info/emailAddress=root@guardianproject.info", $x);
}
public function testVerify() {
$der = file_get_contents(__DIR__ . "/data/pkcs7/1.RSA");
$plain = file_get_contents(__DIR__ . "/data/pkcs7/1.SF");
$pkcs7 = PKCS7::loadFromDER($der);
$signed = $pkcs7->asSigned();
$result = $signed->verify($plain);
}
public function testLoadingGarbageDER()

12
tests/StackTest.php

@ -24,7 +24,7 @@ class StackTest extends TestCase
$stack->push($x509);
$this->assertCount(1, $stack);
$x509Item = $stack->get(0);
$this->assertSame($x509, $x509Item);
$this->assertNotSame($x509, $x509Item);
}
function testSet()
@ -47,14 +47,10 @@ class StackTest extends TestCase
$c = X509::new();
$stack->push($a);
$stack->push($c);
$this->assertEquals(1, $a->getRefCount());
$b = $stack->delete(0);
$this->assertSame($a, $b);
$this->assertCount(1, $stack);
$this->assertEquals(0, $a->getRefCount());
unset($stack[0]);
$this->assertCount(0, $stack);
$this->assertEquals(0, $c->getRefCount());
$this->expectException(\RuntimeException::class);
$stack->delete(1);
@ -67,17 +63,13 @@ class StackTest extends TestCase
$stack->push($x509);
$this->assertCount(1, $stack);
$x509Item = $stack->get(0);
$this->assertSame($x509, $x509Item);
$this->assertEquals(1, $x509->getRefCount());
unset($x509Item, $x509);
/** @var X509 $x509 */
$x509 = $stack->get(0);
$this->assertFalse($x509->free());
$stack->freeAll();
$this->assertEquals(0, $x509->getRefCount());
$this->assertTrue($stack->isFreed());
$this->assertTrue($x509->isFreed());
$this->assertFalse($x509->isFreed());
}
function testAddressingCorrect()

Loading…
Cancel
Save