Given that we have CSR attestion with the old yubico-piv-tool. I really wanted the same functionallity but with the currently updated version. I could not really find an simple option for YubiKey Manager to replace the yubico-piv-tool option --attestation. So what is the option for YubiKey Maanager, I haven’t found one. So what do you do. You learn how to do it with Powershell :)

So this is what I came up with. I use a ykman.exe to create the key, a self signed certificate, the attestation and intermediate certificates, then I turn to Powershell and create the CSR using COM objects.

Lets start by cleaning the yubikey and preparing for the Powershell.

& 'C:\Program Files\Yubico\YubiKey Manager\ykman.exe' piv reset -f
& 'C:\Program Files\Yubico\YubiKey Manager\ykman.exe' piv keys generate --pin-policy ONCE --touch-policy CACHED --algorithm RSA2048 --management-key 010203040506070801020304050607080102030405060708 9a "$($env:TEMP)\junkfile"
& 'C:\Program Files\Yubico\YubiKey Manager\ykman.exe' piv certificates generate -s "CN=Selfsigned" --pin 123456 --management-key 010203040506070801020304050607080102030405060708 9a "$($env:TEMP)\junkfile"
& 'C:\Program Files\Yubico\YubiKey Manager\ykman.exe' piv objects generate --management-key 010203040506070801020304050607080102030405060708 chuid
& 'C:\Program Files\Yubico\YubiKey Manager\ykman.exe' piv certificates  export f9  "$($env:TEMP)\yubico_intermediate.cer"
& 'C:\Program Files\Yubico\YubiKey Manager\ykman.exe' piv keys attest 9a "$($env:TEMP)\yubico_attestation.cer"

This creates a RSA 2048 bit key with policies as I wanted them.

Now that we have all components lets start building it.

Lets start with reading in the attestation certificate and intermediate certificate.

$attcertbin = (GC "$($env:TEMP)\yubico_attestation.cer") -replace '^-.*-$' -join '' -Replace '[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx yz0123456789+/=]'
$intcertbin = (GC "$($env:TEMP)\yubico_intermediate.cer") -replace '^-.*-$' -join '' -Replace '[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx yz0123456789+/=]'
Then we create the CSR extensions that we will use to store the certificates in the CSR.
$CertExtAttestation = New-Object -ComObject X509Enrollment.CX509Extension
$oidExtAtt = New-Object -ComObject X509Enrollment.CObjectId
$oidExtAtt.InitializeFromValue('1.3.6.1.4.1.41482.3.11')

$CertExtInt = New-Object -ComObject X509Enrollment.CX509Extension
$oidExtInt = New-Object -ComObject X509Enrollment.CObjectId
$oidExtint.InitializeFromValue('1.3.6.1.4.1.41482.3.2')
# Second paramater is Encoding, and 1 = XCN_CRYPT_STRING_BASE64
$CertExtAttestation.Initialize($oidExtAtt, 1, $attcertbin)
$CertExtInt.Initialize($oidExtInt, 1, $intcertbin)
Next lets open the private key so we can create a new CSR
# We create a privatekey object and supply the length and pin.
$privkey = New-Object -ComObject X509Enrollment.CX509PrivateKey
$privkey.Length=2048
$privkey.Pin ='123456'
#Here we specify that Windows should look for this one as a Smart Card, and send in all cryptographic providers we find
$privkey.ProviderName = "Microsoft Base Smart Card Crypto Provider";
$CCspInformations = New-Object -ComObject X509Enrollment.CCspInformations
$CCspInformations.AddAvailableCsps()
$privkey.CspInformations =$CCspInformations
$privkey.ContainerName = $Null
$privkey.Open()
Now we should have found the private key and can continue with the CSR. This will require a press on the yubikey if you have set that requirement.
$CertificateSigningRequest = New-Object -ComObject X509enrollment.CX509CertificateRequestPkcs10
$CertificateSigningRequest.InitializeFromPrivateKey(1, $privkey, '')
$SubjectDN = New-Object -ComObject X509Enrollment.CX500DistinguishedName
#the second paramater is X500NameFlags, and 0x0 = XCN_CERT_NAME_STR_NONE
$SubjectDN.Encode('CN=There must be a DN in a CSR', 0x0)
$CertificateSigningRequest.Subject = $SubjectDN
$CertificateSigningRequest.X509Extensions.Add($CertExtAttestation)
$CertificateSigningRequest.X509Extensions.Add($CertExtInt)
#Requires interaction with private key and therefor press on yubikey depending on policy.
$CertificateSigningRequest.Encode()
Now we can take this and create the CSR file using the x509 enrollment file.
$en = New-Object -ComObject X509enrollment.cx509enrollment
$en.InitializeFromRequest($CertificateSigningRequest)
# The only paramater is Encoding, and 1 = XCN_CRYPT_STRING_BASE64
$en.CreateRequest(1)