diff --git a/Dockerfile b/Dockerfile index ec1f761..4a07325 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,9 +10,9 @@ COPY . /app RUN echo 12345678 > pin RUN echo 123456 > user-pin RUN sh /start.sh && \ - ./opgpcard admin --card 0000:00000000 --admin-pin pin import sample-rsa-key.asc && \ - ./opgpcard status --card 0000:00000000 && \ + opgpcard admin --card 0000:00000000 --admin-pin pin import sample-rsa-key.asc && \ + opgpcard status --card 0000:00000000 && \ bash run.sh && \ - ./opgpcard admin --card 0000:00000000 --admin-pin pin import sample-ec-key.asc && \ - ./opgpcard status --card 0000:00000000 && \ + opgpcard admin --card 0000:00000000 --admin-pin pin import sample-ec-key.asc && \ + opgpcard status --card 0000:00000000 && \ bash run.sh diff --git a/openpgp_cards.h b/openpgp_cards.h index 5de7386..c7aa9d4 100644 --- a/openpgp_cards.h +++ b/openpgp_cards.h @@ -15,6 +15,14 @@ typedef enum opc_CCardError { opc_CCardError_TooShortBuffer, } opc_CCardError; +typedef enum opc_CCardSignMode { + opc_CCardSignMode_RsaSha256, + opc_CCardSignMode_RsaSha384, + opc_CCardSignMode_RsaSha512, + opc_CCardSignMode_EdDSA, + opc_CCardSignMode_ECDSA, +} opc_CCardSignMode; + typedef struct opc_CCard opc_CCard; typedef struct opc_CCards opc_CCards; @@ -42,4 +50,13 @@ enum opc_CCardError opc_card_decipher(struct opc_CCard *card, uint8_t *plaintext, size_t *plaintext_len); +OPC_API +enum opc_CCardError opc_card_sign(struct opc_CCard *card, + const int8_t *pin, + enum opc_CCardSignMode mode, + const uint8_t *digest, + size_t digest_len, + uint8_t *signature, + size_t *signature_len); + OPC_API void opc_free_cards(struct opc_CCards *cards); diff --git a/opgpcard b/opgpcard deleted file mode 100755 index d84ab02..0000000 Binary files a/opgpcard and /dev/null differ diff --git a/sample.c b/sample.c index 7237502..c1902dc 100644 --- a/sample.c +++ b/sample.c @@ -12,10 +12,14 @@ int main() { opc_CCard *const card = opc_get_card(cards, i); const char *ident = opc_get_card_ident(card); printf(" - %s\n", ident); - printf(" SIG: %s\n", opc_get_card_sig_fpr(card)); + + const char *sig = opc_get_card_sig_fpr(card); + printf(" SIG: %s\n", sig); + const char *dec = opc_get_card_dec_fpr(card); printf(" DEC: %s\n", dec); printf(" AUT: %s\n", opc_get_card_aut_fpr(card)); + if (strcmp(dec, "4AF56C624C9F9D877EB5954E95C3E680713DCCA9") == 0) { // this subkey is an RSA key unsigned char ciphertext[] = { @@ -75,6 +79,47 @@ int main() { for (int i = 0; i < plaintext_len; i++) { printf("%x ", plaintext[i]); } + printf("\n"); + free(plaintext); + } + + if (strcmp(sig, "46C4C8819CCD4A2FBBEB461FAF8A642682A0C8B8") == 0) { + // RSA sign + unsigned char digest[] = { + 115, 41, 79, 251, 178, 109, 143, 166, 223, 139, 207, 44, 186, + 112, 132, 218, 104, 228, 80, 5, 144, 213, 106, 49, 10, 61, + 243, 34, 143, 83, 153, 144, 157, 206, 65, 229, 145, 139, 64, + 116, 203, 0, 194, 110, 2, 133, 45, 62, 92, 152, 93, 88, + 215, 209, 190, 197, 236, 198, 142, 42, 23, 103, 88, 83}; + size_t signature_len = 1024; + unsigned char *signature = malloc(signature_len); + printf("RSA signed: %d: ", + opc_card_sign(card, "123456", opc_CCardSignMode_RsaSha512, digest, + sizeof(digest), signature, &signature_len)); + for (int i = 0; i < signature_len; i++) { + printf("%x ", signature[i]); + } + printf("\n"); + free(signature); + } else if (strcmp(sig, "BEBE0B48F334CF9439259F7B94C42D7E8B31A1B5") == 0) { + // ECDH + unsigned char digest[] = { + 137, 122, 199, 107, 209, 113, 138, 78, 207, 252, 223, 252, 204, + 219, 1, 139, 143, 55, 155, 17, 11, 12, 59, 213, 223, 149, + 54, 100, 128, 223, 28, 0, 194, 204, 191, 90, 170, 188, 48, + 231, 163, 226, 189, 161, 147, 255, 82, 209, 36, 184, 125, 156, + 127, 93, 49, 93, 9, 158, 97, 14, 205, 185, 224, 207}; + + size_t signature_len = 1024; + unsigned char *signature = malloc(signature_len); + printf("EdDSA signed: %d: ", + opc_card_sign(card, "123456", opc_CCardSignMode_EdDSA, digest, + sizeof(digest), signature, &signature_len)); + for (int i = 0; i < signature_len; i++) { + printf("%x ", signature[i]); + } + printf("\n"); + free(signature); } } opc_free_cards(cards); diff --git a/src/lib.rs b/src/lib.rs index ec347ea..ef932a1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,8 @@ use std::{ slice, }; +use openpgp_card::crypto_data::Hash; + pub struct CCards { cards: Vec, } @@ -28,6 +30,15 @@ pub enum CCardDecipherMode { Ecdh, } +#[repr(C)] +pub enum CCardSignMode { + RsaSha256, + RsaSha384, + RsaSha512, + EdDSA, + ECDSA, +} + #[no_mangle] pub extern "C" fn opc_scan_for_cards(cards: *mut *mut CCards) -> CCardError { env_logger::init(); // FIXME: drop this as soon as debugging is done @@ -136,6 +147,38 @@ pub unsafe extern "C" fn opc_card_decipher( } } +#[no_mangle] +pub unsafe extern "C" fn opc_card_sign( + card: *mut CCard, + pin: *const i8, + mode: CCardSignMode, + digest: *const u8, + digest_len: usize, + signature: *mut u8, + signature_len: *mut usize, +) -> CCardError { + let mut tx = (*card).raw_card.transaction().unwrap(); + let pin = CStr::from_ptr(pin); + tx.verify_pw1_sign(pin.to_bytes()).unwrap(); + let digest = slice::from_raw_parts(digest, digest_len); + let hash = match mode { + CCardSignMode::RsaSha256 => Hash::SHA256(digest.try_into().unwrap()), + CCardSignMode::RsaSha384 => Hash::SHA384(digest.try_into().unwrap()), + CCardSignMode::RsaSha512 => Hash::SHA512(digest.try_into().unwrap()), + CCardSignMode::ECDSA => Hash::ECDSA(digest.try_into().unwrap()), + CCardSignMode::EdDSA => Hash::EdDSA(digest.try_into().unwrap()), + }; + let signed = tx.signature_for_hash(hash).unwrap(); + if signed.len() > *signature_len { + CCardError::TooShortBuffer + } else { + let signature = slice::from_raw_parts_mut(signature, *signature_len); + signature[0..signed.len()].copy_from_slice(&signed); + *signature_len = signed.len(); + CCardError::Success + } +} + #[no_mangle] pub unsafe extern "C" fn opc_free_cards(cards: *mut CCards) { drop(Box::from_raw(cards)); diff --git a/statement.txt b/statement.txt new file mode 100644 index 0000000..36ffaa2 --- /dev/null +++ b/statement.txt @@ -0,0 +1 @@ +I like strawberries