-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathverify.c
More file actions
120 lines (111 loc) · 4.48 KB
/
verify.c
File metadata and controls
120 lines (111 loc) · 4.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <stdarg.h>
#include <string.h>
#include "pgpr_internal.h"
pgprRC pgprVerifySignatureRaw(pgprItem key, pgprItem sig, const uint8_t *hash, size_t hashlen)
{
/* make sure the parameters are correct and the pubkey algo matches */
if (sig == NULL || sig->tag != PGPRTAG_SIGNATURE)
return PGPR_ERROR_BAD_ARGUMENT;
if (key == NULL || (key->tag != PGPRTAG_PUBLIC_KEY && key->tag != PGPRTAG_PUBLIC_SUBKEY))
return PGPR_ERROR_BAD_ARGUMENT;
if (hash == NULL || hashlen < 2 || hashlen != pgprDigestLength(sig->hash_algo))
return PGPR_ERROR_BAD_ARGUMENT;
if (sig->pubkey_algo != key->pubkey_algo)
return PGPR_ERROR_BAD_SIGNATURE;
/* Compare leading 16 bits of digest for a quick check. */
if (memcmp(hash, sig->signhash16, 2) != 0)
return PGPR_ERROR_BAD_SIGNATURE;
if (key->version < 4)
return PGPR_ERROR_UNSUPPORTED_VERSION;
if (key->version == 6 && sig->version != 6)
return PGPR_ERROR_BAD_SIGNATURE;
if (sig->pubkey_algo == PGPRPUBKEYALGO_MLDSA65_ED25519 || sig->pubkey_algo == PGPRPUBKEYALGO_MLDSA87_ED448) {
if (sig->version < 6 || hashlen < 32)
return PGPR_ERROR_REJECTED_SIGNATURE;
}
return pgprAlgVerify(sig->alg, key->alg, hash, hashlen, sig->hash_algo);
}
pgprRC pgprVerifySignature(pgprItem key, pgprItem sig, const uint8_t *hash, size_t hashlen, char **lints)
{
pgprRC rc = PGPR_ERROR_BAD_SIGNATURE; /* assume failure */
if (lints)
*lints = NULL;
if (!sig || sig->tag != PGPRTAG_SIGNATURE || (sig->sigtype != PGPRSIGTYPE_BINARY && sig->sigtype != PGPRSIGTYPE_TEXT && sig->sigtype != PGPRSIGTYPE_STANDALONE))
goto exit;
if (!key || (key->tag != PGPRTAG_PUBLIC_KEY && key->tag != PGPRTAG_PUBLIC_SUBKEY))
goto exit;
rc = pgprVerifySignatureRaw(key, sig, hash, hashlen);
if (rc != PGPR_OK)
goto exit;
/* now check the meta information of the signature */
if ((sig->saved & PGPRITEM_SAVED_SIG_EXPIRE) != 0 && sig->sig_expire) {
uint32_t now = pgprCurrentTime();
if (now < sig->time) {
if (lints)
pgprAddLint(sig, lints, PGPR_ERROR_SIGNATURE_FROM_FUTURE);
rc = PGPR_ERROR_SIGNATURE_FROM_FUTURE;
} else if (sig->sig_expire < now - sig->time) {
if (lints)
pgprAddLint(sig, lints, PGPR_ERROR_SIGNATURE_EXPIRED);
rc = PGPR_ERROR_SIGNATURE_EXPIRED;
}
if (rc != PGPR_OK)
goto exit;
}
/* now check the meta information of the key */
if (key->revoked) {
rc = key->revoked == PGPRITEM_REVOKED_MAINKEY ? PGPR_ERROR_PRIMARY_REVOKED : PGPR_ERROR_KEY_REVOKED;
if (lints)
pgprAddLint(key, lints, rc);
} else if ((key->saved & PGPRITEM_SAVED_VALID) == 0) {
rc = PGPR_ERROR_KEY_NOT_VALID;
if (lints)
pgprAddLint(key, lints, rc);
} else if (key->tag == PGPRTAG_PUBLIC_KEY && (key->saved & PGPRITEM_SAVED_KEY_FLAGS) != 0 && (key->key_flags & PGPRKEYFLAGS_SIGN) == 0) {
rc = PGPR_ERROR_KEY_NO_SIGNING;
if (lints)
pgprAddLint(key, lints, rc);
} else if (key->tag == PGPRTAG_PUBLIC_SUBKEY && ((key->saved & PGPRITEM_SAVED_KEY_FLAGS) == 0 || (key->key_flags & PGPRKEYFLAGS_SIGN) == 0)) {
rc = PGPR_ERROR_KEY_NO_SIGNING;
if (lints)
pgprAddLint(key, lints, rc);
} else if (key->time > sig->time) {
rc = PGPR_ERROR_KEY_CREATED_AFTER_SIG;
if (lints)
pgprAddLint(key, lints, rc);
} else if ((key->saved & PGPRITEM_SAVED_KEY_EXPIRE) != 0 && key->key_expire && key->key_expire < sig->time - key->time) {
rc = PGPR_ERROR_KEY_EXPIRED;
if (lints)
pgprAddLint(key, lints, rc);
}
exit:
return rc;
}
pgprRC pgprVerifySignatureNoKey(pgprItem sig, const uint8_t *hash, size_t hashlen, char **lints)
{
if (lints)
*lints = NULL;
if (!sig || sig->tag != PGPRTAG_SIGNATURE || (sig->sigtype != PGPRSIGTYPE_BINARY && sig->sigtype != PGPRSIGTYPE_TEXT && sig->sigtype != PGPRSIGTYPE_STANDALONE))
return PGPR_ERROR_BAD_SIGNATURE;
if (hash) {
if (hashlen == 0 || hashlen != pgprDigestLength(sig->hash_algo))
return PGPR_ERROR_INTERNAL;
/* Compare leading 16 bits of digest for a quick check. */
if (memcmp(hash, sig->signhash16, 2) != 0)
return PGPR_ERROR_BAD_SIGNATURE;
}
/* now check the meta information of the signature */
if ((sig->saved & PGPRITEM_SAVED_SIG_EXPIRE) != 0 && sig->sig_expire) {
uint32_t now = pgprCurrentTime();
if (now < sig->time) {
if (lints)
pgprAddLint(sig, lints, PGPR_ERROR_SIGNATURE_FROM_FUTURE);
return PGPR_ERROR_SIGNATURE_FROM_FUTURE;
} else if (sig->sig_expire < now - sig->time) {
if (lints)
pgprAddLint(sig, lints, PGPR_ERROR_SIGNATURE_EXPIRED);
return PGPR_ERROR_SIGNATURE_EXPIRED;
}
}
return PGPR_OK;
}