Skip to content

Commit f60b0ff

Browse files
Added SecCertificateCopyExtensionValue
1 parent bb94931 commit f60b0ff

2 files changed

Lines changed: 84 additions & 2 deletions

File tree

sec/SecCertificate.test.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1+
import { Bool8Ptr, Int32Ptr, Uint8Ptr } from '@hqtsm/struct';
12
import { assertEquals, assertInstanceOf } from '@std/assert';
23
import { INT32_MAX, INT32_MIN, UINT32_MAX } from '../libc/stdint.ts';
34
import { digest } from '../spec/hash.ts';
45
import {
56
__SecCertificate,
67
GetDecimalValueOfString,
8+
SecCertificateCopyExtensionValue,
79
SecCertificateCopyIssuerSHA256Digest,
810
SecCertificateCopySHA1Digest,
911
SecCertificateCreateOidDataFromString,
12+
SecCertificateExtension,
1013
SecCertificateIsOidString,
1114
} from './SecCertificate.ts';
12-
import { Int32Ptr, Uint8Ptr } from '@hqtsm/struct';
1315

1416
export const ABCD = new Uint8Array([...'ABCD'].map((c) => c.charCodeAt(0)));
1517

@@ -131,3 +133,35 @@ Deno.test('SecCertificateCreateOidDataFromString', () => {
131133
new Uint8Array([40 + 39, 0x87, 0xFF, 0xFF, 0xFF, 0x7F]),
132134
);
133135
});
136+
137+
Deno.test('SecCertificateCopyExtensionValue', () => {
138+
const b = new Bool8Ptr(new ArrayBuffer(1));
139+
const sce = new SecCertificateExtension();
140+
const sc = new __SecCertificate();
141+
const oid = '1.2.3';
142+
const oidData = SecCertificateCreateOidDataFromString(oid)!;
143+
144+
sce.extnID.data = new Uint8Ptr(oidData.buffer);
145+
sce.extnID.length = oidData.byteLength;
146+
sce.critical = true;
147+
sce.extnValue.data = new Uint8Ptr(ABCD.buffer.slice());
148+
sce.extnValue.length = ABCD.byteLength;
149+
150+
sc._extensionCount = 1;
151+
sc._extensions = [sce];
152+
153+
assertEquals(SecCertificateCopyExtensionValue(null, null, null), null);
154+
assertEquals(SecCertificateCopyExtensionValue(sc, null, null), null);
155+
assertEquals(SecCertificateCopyExtensionValue(sc, '', null), null);
156+
assertEquals(SecCertificateCopyExtensionValue(sc, 'BAD', null), null);
157+
158+
assertEquals(SecCertificateCopyExtensionValue(sc, oid, b), ABCD);
159+
assertEquals(b[0], true);
160+
161+
sce.critical = false;
162+
163+
assertEquals(SecCertificateCopyExtensionValue(sc, oidData, b), ABCD);
164+
assertEquals(b[0], false);
165+
166+
assertEquals(SecCertificateCopyExtensionValue(sc, '1.1.1', b), null);
167+
});

sec/SecCertificate.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@ import { toStringTag } from '@hqtsm/class';
22
import { Int32Ptr, type Ptr } from '@hqtsm/struct';
33
import type { CFIndex } from '../CoreFoundation/CFBase.ts';
44
import type { SubtleCryptoDigest } from '../helpers/crypto.ts';
5-
import { bufferBytes } from '../helpers/memory.ts';
5+
import {
6+
type ArrayBufferLikeData,
7+
bufferBytes,
8+
pointerBytes,
9+
viewBytes,
10+
} from '../helpers/memory.ts';
611
import type { bool } from '../libc/c.ts';
712
import { INT32_MAX, type int32_t } from '../libc/stdint.ts';
813
import { DERItem } from '../libDER/DERItem.ts';
914
import type { SecCertificateRef } from '../Security/SecBase.ts';
1015
import { SecSHA1DigestCreate, SecSHA256DigestCreate } from './SecDigest.ts';
16+
import { memcmp } from '../libc/string.ts';
1117

1218
/**
1319
* X.509 certificate extension.
@@ -199,3 +205,45 @@ export function SecCertificateCreateOidDataFromString(
199205

200206
return new Uint8Array(bytes);
201207
}
208+
209+
/**
210+
* Get extension value.
211+
*
212+
* @param certificate Certificate.
213+
* @param extensionOID OID.
214+
* @param isCritical Is critical.
215+
* @returns Extension value.
216+
*/
217+
export function SecCertificateCopyExtensionValue(
218+
certificate: SecCertificateRef | null,
219+
extensionOID: string | ArrayBufferLikeData | null,
220+
isCritical: Ptr<bool> | null,
221+
): Uint8Array<ArrayBuffer> | null {
222+
if (!certificate || !extensionOID) {
223+
return null;
224+
}
225+
226+
const oidData = typeof extensionOID === 'string'
227+
? SecCertificateCreateOidDataFromString(extensionOID)
228+
: viewBytes(extensionOID);
229+
if (!oidData) {
230+
return null;
231+
}
232+
233+
const oidLen = oidData.byteLength;
234+
for (let ix = 0; ix < certificate._extensionCount; ++ix) {
235+
const extn = certificate._extensions![ix];
236+
if (
237+
extn.extnID.length === oidLen &&
238+
!memcmp(extn.extnID.data!, oidData, oidLen)
239+
) {
240+
if (isCritical) {
241+
isCritical[0] = extn.critical;
242+
}
243+
return pointerBytes(extn.extnValue.data!, extn.extnValue.length)
244+
.slice();
245+
}
246+
}
247+
248+
return null;
249+
}

0 commit comments

Comments
 (0)