<# .SYNOPSIS PEM 인증서 파일로부터 firmware/certs/server_ca.c 를 재생성한다. .DESCRIPTION Cafe24 서버 루트 CA(필요 시 intermediate+root 를 연결한 체인) PEM 을 읽어, mbedTLS 가 그대로 파싱할 수 있는 C 문자열 리터럴 형태로 server_ca.c 에 임베드한다. - 각 PEM 라인을 "....\n" C 리터럴로 변환(끝의 종결 NUL 은 sizeof 에 포함). - SERVER_CA_PEM_LEN = sizeof(SERVER_CA_PEM) 로 정의(NUL 포함 → mbedTLS 요구). - 폐쇄망: 이 스크립트는 *빌드 머신*에서만 실행. 타깃은 결과 .c 만 컴파일. .PARAMETER PemPath 입력 PEM 파일 경로(.pem/.crt). 하나 이상의 -----BEGIN CERTIFICATE----- 블록 포함. .PARAMETER OutPath 출력 C 파일 경로. 기본값: 이 스크립트와 같은 폴더의 server_ca.c .EXAMPLE ./gen_ca_header.ps1 -PemPath cafe24_root.pem .EXAMPLE # 체인 추출 → 헤더 생성 (한 번에) openssl s_client -showcerts -connect your-domain.example:443 -servername your-domain.example [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [string]$PemPath, [Parameter(Position = 1)] [string]$OutPath = (Join-Path $PSScriptRoot 'server_ca.c') ) $ErrorActionPreference = 'Stop' # --- 입력 검증 ---------------------------------------------------------------- if (-not (Test-Path -LiteralPath $PemPath)) { throw "PEM 파일을 찾을 수 없습니다: $PemPath" } # CRLF/CR 을 LF 로 정규화하고 라인 분해. 빈 끝줄은 제거. $raw = Get-Content -LiteralPath $PemPath -Raw $normalized = $raw -replace "`r`n", "`n" -replace "`r", "`n" $lines = $normalized -split "`n" # 최소한 BEGIN/END CERTIFICATE 마커가 있어야 한다. if (-not ($normalized -match '-----BEGIN CERTIFICATE-----')) { throw "유효한 PEM 인증서 블록(-----BEGIN CERTIFICATE-----)이 없습니다: $PemPath" } if (-not ($normalized -match '-----END CERTIFICATE-----')) { throw "PEM 종료 마커(-----END CERTIFICATE-----)가 없습니다: $PemPath" } # 인증서 블록 개수(intermediate+root 연결이면 2개 이상). $certCount = ([regex]::Matches($normalized, '-----BEGIN CERTIFICATE-----')).Count # --- C 문자열 리터럴로 변환 --------------------------------------------------- # 후행 빈 라인 제거(마지막 -----END----- 뒤의 공백 라인). $body = New-Object System.Collections.Generic.List[string] foreach ($line in $lines) { $body.Add($line) | Out-Null } while ($body.Count -gt 0 -and [string]::IsNullOrEmpty($body[$body.Count - 1])) { $body.RemoveAt($body.Count - 1) } # 각 라인을 C escape: 백슬래시/큰따옴표 이스케이프 후 "...\n" 형태로. $escapedLines = foreach ($line in $body) { $esc = $line -replace '\\', '\\' -replace '"', '\"' ' "' + $esc + '\n"' } $generatedAt = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss zzz') $pemFileName = Split-Path -Leaf $PemPath $header = @" /* ============================================================================= * server_ca.c - 서버 루트 CA 인증서 (PEM, flash 임베드) [자동 생성] * * gen_ca_header.ps1 로 자동 생성됨. 직접 편집하지 말 것. * source PEM : $pemFileName * 생성 시각 : $generatedAt * 인증서 블록: $certCount 개 * * mbedTLS PEM 요구사항: SERVER_CA_PEM_LEN 은 종결 NUL 을 포함해야 한다 * → sizeof(SERVER_CA_PEM) 사용. * 위험 R3: 인증서 만료/교체 시 이 파일 재생성 + 펌웨어 재배포 필요. * ===========================================================================*/ #include "server_ca.h" const char SERVER_CA_PEM[] = "@ $footer = @" ; /* 길이: 종결 NUL 포함(mbedTLS PEM 요구). */ const unsigned int SERVER_CA_PEM_LEN = sizeof(SERVER_CA_PEM); "@ $content = $header + "`n" + ($escapedLines -join "`n") + $footer + "`n" # UTF-8 (BOM 없음) 로 기록 — arm-none-eabi-gcc 가 깔끔히 읽도록. $utf8NoBom = New-Object System.Text.UTF8Encoding($false) [System.IO.File]::WriteAllText($OutPath, $content, $utf8NoBom) Write-Host "[OK] $OutPath 생성 완료 (인증서 블록 $certCount 개, source: $pemFileName)"