-
Notifications
You must be signed in to change notification settings - Fork 81
[CM-22] Authority Key Identifier support #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
src/ArduinoCloud.cpp
Outdated
const byte authorityKeyIdentifier[20] = { | ||
0xb2, 0xed, 0xef, 0xed, 0x3b, 0xbf, 0xc7, 0x71, 0x75, 0x24, 0x33, 0xd1, 0xae, 0x8b, 0x54, 0xed, 0x97, 0x14, 0x7a, 0x1d | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mattiabertorello I've hardcoded the value in the lib. for now.
Will this value be constant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The value of the authorityKeyIdentifier must be saved in the crypto chip and initialized during the provisioning sketch, so it can change because you can sign the csr with different ca.
For example we will have a CA for dev and another CA for prod
But to support the actual flow during the provisioning sketch if the authorityKeyIdentifier field is empty, no error should be throw.
Thanks
A tip
If you put the issue key in the pull request you will link the PR with the issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made changes in
b264428 to persist this value in the crypto chip and prompt for in during provisioning sketch.
int inLength = in.length(); | ||
in.toUpperCase(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
authorityKeyIdentifier
wasn't being capitalized. To prevent that from happening in the future, I added this line and remove the others about serialNumber
and signature
.
@@ -190,6 +188,6 @@ void hexStringToBytes(const String& in, byte out[], int length) { | |||
byte highByte = (highChar <= '9') ? (highChar - '0') : (highChar + 10 - 'A'); | |||
byte lowByte = (lowChar <= '9') ? (lowChar - '0') : (lowChar + 10 - 'A'); | |||
|
|||
out[outLength++] = (highByte << 4) | lowByte; | |||
out[outLength++] = (highByte << 4) | (lowByte & 0xF); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this mask will prevent lowByte
to overflow
@sandeepmistry There is a problem with the reconstruction of the certificate. Martino and I resolved it parly in the last commit, but still the signature in the reconstructed certificate is slightly different from the original. It seems that some bytes are being added at the beginning of the signature and some in the middle. For example, this is the certificate i tried to store on the board:
and this is the certificate reconstructed by the sketch:
If you compare them (https://text-compare.com/) you'll see the differences in the signature. |
@sandeepmistry Apparently the problem lies in the format of the signature we send to the sketch, because it includes ASN1 metadata about the bitstream. For now, I'm just adding these lines to the Provisioning sketch to remove the unwanted bytes. if (signature.length() == 128) {
// do nothing, already in binary format
} else if (signature.length() == 144) {
// ASN.1 format with a sequence (0x30 0x46) of 2 integers of len 33 (0x02 0x21)
signature = signature.substring(10, 10+64) + signature.substring(80, 80+64);
} else {
// ASN.1 format with a sequence (0x30 0x46) of 2 integers of len 32 (0x02 0x20)
signature = signature.substring(8, 8+64) + signature.substring(76, 76+64);
} This allows to store the certificate correctly, but i'm not sure this is the right solution. Anyway, whatever is the solution, I guess it would be better to implement it in the library itself instead of in the sketch. |
@AlbyIanna can we get the API side fixed? This was working before right? |
var data struct {
X, Y *big.Int
}
_, err = asn1.Unmarshal(cert.Signature, &data)
if err != nil {
panic(errors.Wrapf(err, "unmarshal asn1"))
}
res := app.ArduinoCompressedv1{
Serial: fmt.Sprintf("%032x", cert.SerialNumber),
NotBefore: cert.NotBefore,
NotAfter: cert.NotAfter,
Signature: fmt.Sprintf("%064x%064x", data.X, data.Y),
} I found out in version v1 of iot-api the code that split the signature in two big.Int the signature but in v2 this part of code is absent res.Compressed = &app.ArduinoCompressedv2{
Serial: fmt.Sprintf("%x", cert.SerialNumber),
NotBefore: cert.NotBefore,
NotAfter: cert.NotAfter,
Signature: fmt.Sprintf("%x", cert.Signature),
} So the problem It caused by the missing lines. This is because if a user want to run the provisioning sketch he can do it only with openssl command line tool and copy the signature from the output of the tool |
I disagree still :) If the goal is to use with Arduino Cloud, not many of our user base will use openssl cli. |
That's a good point but we lost a lot of days for that only to understand what was the problem. |
I'm up for adding validation in the sketch. However, the real concern is why the API's on the server side changed so much once we had a spec we agreed to and was stable. |
Ok we decide that for the moment we will restore the same behavior of the V1 API but with different name. You can follow the change on this issue https://arduino.atlassian.net/browse/CM-146 |
Now it seems to me that everything is working fine. @sandeepmistry can we merge this? |
As requested in #4. @mattiabertorello this needs some testing.
I believe after this is merged, all existing provisioned devices will be invalid.