crtman/internal/store/storage.go
2025-10-12 20:01:19 +08:00

123 lines
2.7 KiB
Go

package store
import (
"context"
"crypto/ecdsa"
"crypto/x509"
"database/sql"
"log"
"math/big"
"sync"
_ "github.com/mattn/go-sqlite3"
)
var DB *sql.DB
var RootCA []byte
var RootCAKey *ecdsa.PrivateKey
var SerialLock sync.Mutex
var Serial big.Int
func InitStore(path string) {
var err error
DB, err = sql.Open("sqlite3", path)
if err != nil {
log.Fatal(err)
}
}
func CloseStore() {
DB.Close()
}
func ChekInit() bool {
result := DB.QueryRow("select id,cert,key,serial from syscfg order by id desc limit 1")
if result.Err() != nil {
log.Println(result.Err())
return false
}
var placeholder int
var temp_serial, temp_ca_key []byte
err := result.Scan(&placeholder, &RootCA, &temp_ca_key, &temp_serial)
if err != nil {
log.Println(err)
return false
}
Serial.SetBytes(temp_serial)
RootCAKey, err = x509.ParseECPrivateKey(temp_ca_key)
if err != nil {
log.Println(err)
return false
}
return true
}
func initSchema(tx *sql.Tx) {
_, err := tx.Exec(`
create table syscfg (id integer not null primary key autoincrement, cert blob not null, key blob not null, serial blob not null);
delete from syscfg;
`)
if err != nil {
log.Fatal(err)
}
_, err = tx.Exec(`
create table leaf (id blob not null primary key, cert blob not null, owner text not null, revokeAt datetime, revokeReason integer);
delete from leaf;
`)
}
func InitStoreData() {
ctx := context.Background()
tx, err := DB.BeginTx(ctx, nil)
if err != nil {
log.Fatal(err)
}
initSchema(tx)
temp_ca_key, err := x509.MarshalECPrivateKey(RootCAKey)
if err != nil {
log.Fatal(err)
}
tx.Exec(`
insert into syscfg(cert,key,serial) values(?,?,?)
`, RootCA, temp_ca_key, Serial.Bytes())
err = tx.Commit()
if err != nil {
log.Fatal(err)
}
}
func InsertCert(cert []byte, applicant string) {
parse, err := x509.ParseCertificate(cert)
if err != nil {
log.Println(err)
return
}
DB.Exec("insert into syscfg(id,cert,owner) values(?,?,?)", parse.SerialNumber.Bytes(), cert, applicant)
}
type LeafCert struct {
Cert_org []byte
Cert *x509.Certificate
RevokeAt sql.NullTime
RevokeReason sql.NullInt16
}
func GetLeafCert(serial_num *big.Int) sql.Null[LeafCert] {
var err error
result := DB.QueryRow("select cert,revokeAt, revokeReason from leaf where id = ?", serial_num.Bytes())
var leaf LeafCert
if result.Err() != nil {
log.Println(result.Err())
return sql.Null[LeafCert]{Valid: false}
}
err = result.Scan(&leaf.Cert_org, &leaf.RevokeAt, &leaf.RevokeReason)
if err != nil {
log.Println(err)
return sql.Null[LeafCert]{Valid: false}
}
leaf.Cert, err = x509.ParseCertificate(leaf.Cert_org)
if err != nil {
log.Println(err)
return sql.Null[LeafCert]{Valid: false}
}
return sql.Null[LeafCert]{V: leaf, Valid: true}
}